{"_id":"teambition-sdk","_rev":"884-d2336e8c0640b33c1f4295d562bedda5","name":"teambition-sdk","description":"Front-End SDK for Teambition","dist-tags":{"latest":"0.12.95","false":"0.9.0-alpha.2","alpha":"0.12.87-alpha.0-personalorg","prerelease":"0.12.95-alpha.1","legacy":"0.6.29"},"versions":{"0.0.1":{"name":"teambition-sdk","version":"0.0.1","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","scripts":{"test":"gulp build.test && gulp test","tsd":"ts-node tools/tasks/tsd.ts","serve":"ts-node tools/tasks/serve.ts","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --suppressImplicitAnyIndexErrors","build_es6":"rm -rf dist/es6 && gulp bundle.es6","build_bundle":"rm -rf dist/bundle && gulp build.sdk","build_mock":"rm -rf dist/mock && gulp build.mock","build_all":"npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_es6","prepublish":"npm run build_all","postinstall":"tsd install && ts-node tools/tasks/tsd.ts"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.5","es6-promise":"^3.0.2","whatwg-fetch":"^0.10.1"},"devDependencies":{"browser-sync":"^2.11.1","chai":"^3.4.1","et-dependency":"^0.3.7","et-template":"^0.3.7","file-loader":"^0.8.5","gulp":"^3.9.0","gulp-istanbul":"^0.10.3","gulp-mocha":"^2.2.0","gulp-sourcemaps":"^1.6.0","gulp-tslint":"^4.2.2","gulp-tslint-stylish":"^1.1.1","gulp-typescript":"^2.10.0","gulp-util":"^3.0.7","gulp-watch":"^4.3.5","mocha":"^2.3.4","opn":"^4.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","source-map-loader":"^0.1.5","ts-loader":"^0.7.2","ts-node":"^0.5.4","tsd":"^0.6.5","tslint":"^3.2.1","typescript":"^1.7.5","webpack":"^1.12.10","zone.js":"^0.5.14"},"gitHead":"8f104fff156d25173e97f23a1c77a4bec26f8215","_id":"teambition-sdk@0.0.1","_shasum":"0244737ac90d0a8efdfa555b5116c56653c3c547","_from":".","_npmVersion":"2.14.12","_nodeVersion":"4.3.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"0244737ac90d0a8efdfa555b5116c56653c3c547","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.0.1.tgz","integrity":"sha512-sI2nP0rDblLvuYWZ5rLXknSN+Zb4Q6sfKxN6xJ91TragSTDZPHRxrhgw9SlodvGPxUf1Rp5tv/oczp/dCzirmA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDClcbQ3+haYPKiAF7onFRfLsCE+HeCgoIN6DmKnZctcQIge7iYCrRKUqu9mRWfnU2Sy+zxY3hd0tlhgujOL0s7aUI="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-13-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.0.1.tgz_1457155109493_0.15908940345980227"},"directories":{}},"0.0.2":{"name":"teambition-sdk","version":"0.0.2","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","scripts":{"test":"gulp build.test && gulp test","tsd":"ts-node tools/tasks/tsd.ts","serve":"ts-node tools/tasks/serve.ts","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --suppressImplicitAnyIndexErrors","build_es6":"rm -rf dist/es6 && gulp bundle.es6","build_bundle":"rm -rf dist/bundle && gulp build.sdk","build_mock":"rm -rf dist/mock && gulp build.mock","build_all":"npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_es6","prepublish":"npm run test && npm run build_all"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.5","es6-promise":"^3.0.2","whatwg-fetch":"^0.10.1"},"devDependencies":{"browser-sync":"^2.11.1","chai":"^3.4.1","et-dependency":"^0.3.7","et-template":"^0.3.7","file-loader":"^0.8.5","gulp":"^3.9.0","gulp-istanbul":"^0.10.3","gulp-mocha":"^2.2.0","gulp-sourcemaps":"^1.6.0","gulp-tslint":"^4.2.2","gulp-tslint-stylish":"^1.1.1","gulp-typescript":"^2.10.0","gulp-util":"^3.0.7","gulp-watch":"^4.3.5","mocha":"^2.3.4","opn":"^4.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","source-map-loader":"^0.1.5","ts-loader":"^0.7.2","ts-node":"^0.5.4","tsd":"^0.6.5","tslint":"^3.2.1","typescript":"^1.7.5","webpack":"^1.12.10","zone.js":"^0.5.14"},"gitHead":"ef70b1ff493087dbd8dc67955b9f4b39f356c858","_id":"teambition-sdk@0.0.2","_shasum":"d9f8381327b20a0967e9b83a800b70028b4d83a4","_from":".","_npmVersion":"2.14.12","_nodeVersion":"4.3.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"d9f8381327b20a0967e9b83a800b70028b4d83a4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.0.2.tgz","integrity":"sha512-v0fACR00MKqPNBW59UuO+TJ1743r2ksr3BASrGqIKmqOuIKTgdGhmCBN+WEw/mG26uEx9XmjEUHckNnY2X36ug==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDWLCYu07mn3th4LX7CiK4S0tGYQn/iFJRu6zC1yJuvlAIhALLEKo9qApuIAZwWbLjUc7m/GUd+GlsfpQn5fRytACz8"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-13-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.0.2.tgz_1457155321226_0.8428815207444131"},"directories":{}},"0.0.3":{"name":"teambition-sdk","version":"0.0.3","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","scripts":{"test":"gulp build.test && gulp test","tsd":"ts-node tools/tasks/tsd.ts","serve":"ts-node tools/tasks/serve.ts","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --suppressImplicitAnyIndexErrors","build_es6":"rm -rf dist/es6 && gulp bundle.es6","build_bundle":"rm -rf dist/bundle && gulp build.sdk","build_mock":"rm -rf dist/mock && gulp build.mock","build_all":"npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_es6","prepublish":"npm run test && npm run build_all"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.5","es6-promise":"^3.0.2","whatwg-fetch":"^0.10.1"},"devDependencies":{"browser-sync":"^2.11.1","chai":"^3.4.1","et-dependency":"^0.3.7","et-template":"^0.3.7","file-loader":"^0.8.5","gulp":"^3.9.0","gulp-istanbul":"^0.10.3","gulp-mocha":"^2.2.0","gulp-sourcemaps":"^1.6.0","gulp-tslint":"^4.2.2","gulp-tslint-stylish":"^1.1.1","gulp-typescript":"^2.10.0","gulp-util":"^3.0.7","gulp-watch":"^4.3.5","mocha":"^2.3.4","opn":"^4.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","source-map-loader":"^0.1.5","ts-loader":"^0.7.2","ts-node":"^0.5.4","tsd":"^0.6.5","tslint":"^3.2.1","typescript":"^1.7.5","webpack":"^1.12.10","zone.js":"^0.5.14"},"gitHead":"d10ac959f900d132b2393b2fa3c2ea44357ae59d","_id":"teambition-sdk@0.0.3","_shasum":"b317ee574408e531a63ec8de77f83c184f7d58b0","_from":".","_npmVersion":"2.14.12","_nodeVersion":"4.3.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"b317ee574408e531a63ec8de77f83c184f7d58b0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.0.3.tgz","integrity":"sha512-mT+X0efSyXUkYAtGC2b/lLj/s6JSkQQDIdAyNXI+b948piJT+EoJ0mlK7OJOfEbB7DnyWfJvlA1A4ZCRe4eclg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCRFta6rto3s50FVTUyCCnY/lbzBS1gFuKwQxw7R11jDgIhAOiDXiuV6+KmeFOenJx920WJw4+jJMt71JWpmI3/LJXJ"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.0.3.tgz_1457155459106_0.20439069950953126"},"directories":{}},"0.1.0":{"name":"teambition-sdk","version":"0.1.0","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"gulp build.test && gulp test","tsd":"ts-node tools/tasks/tsd.ts","serve":"ts-node tools/tasks/serve.ts","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --suppressImplicitAnyIndexErrors","build_es6":"rm -rf dist/es6 && gulp bundle.es6","build_bundle":"rm -rf dist/bundle && gulp build.sdk","build_mock":"rm -rf dist/mock && gulp build.mock","build_all":"npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_es6","prepublish":"npm run test && npm run build_all"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.5","es6-promise":"^3.0.2","whatwg-fetch":"^0.10.1"},"devDependencies":{"browser-sync":"^2.11.1","chai":"^3.4.1","et-dependency":"^0.3.7","et-template":"^0.3.7","file-loader":"^0.8.5","gulp":"^3.9.0","gulp-istanbul":"^0.10.3","gulp-mocha":"^2.2.0","gulp-sourcemaps":"^1.6.0","gulp-tslint":"^4.2.2","gulp-tslint-stylish":"^1.1.1","gulp-typescript":"^2.10.0","gulp-util":"^3.0.7","gulp-watch":"^4.3.5","mocha":"^2.3.4","opn":"^4.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","source-map-loader":"^0.1.5","ts-loader":"^0.7.2","ts-node":"^0.5.4","tsd":"^0.6.5","tslint":"^3.2.1","typescript":"^1.8.7","webpack":"^1.12.10","zone.js":"^0.5.14"},"gitHead":"3097109c622332a8b5f8823aff3d8d254ae31752","_id":"teambition-sdk@0.1.0","_shasum":"fdf511303735a0f6eebed27c000476c6345eadcb","_from":".","_npmVersion":"2.14.20","_nodeVersion":"4.4.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"fdf511303735a0f6eebed27c000476c6345eadcb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.1.0.tgz","integrity":"sha512-VaxwD+KFhfWkg9Gl1JFqYYSFzqqm+wRiWgZZira79s7Ck9irdi50M3qm5fa122fj6TzsE45X5+IesoHQb44NoA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICcCiJp2Fz3FkU2JwWi1YhxlGx4NoAUVggdqAOh19axHAiAx8LouGkZien7d00az+3973HzWHyVCWHCaEjq2feh1dw=="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.1.0.tgz_1458120750433_0.6812577694654465"},"directories":{}},"0.2.0":{"name":"teambition-sdk","version":"0.2.0","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","commit":"npm run lint && npm run build_all && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                                  --sourcemap --sourceRoot test      --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle && mkdir dist/bundle && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.8"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","fetch-mock":"^4.5.0","istanbul":"^0.4.3","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-babel":"^2.4.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.7.3","tslint":"^3.10.2","typescript":"^1.8.10","typings":"^1.0.4"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"0bc48d1d370bce4ba23e9194d77b31947610f418","_id":"teambition-sdk@0.2.0","_shasum":"2cab59381ee52c55cb6446aa1496748ae222f1b5","_from":".","_npmVersion":"2.15.5","_nodeVersion":"4.4.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"2cab59381ee52c55cb6446aa1496748ae222f1b5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.0.tgz","integrity":"sha512-t4D/5d937I0IjY2geFas70V4L3c9rStgUsmjzeDrquzw4kaPY0s8OXTONqvqC1qqozSx/2aDjSVeI356FOQVGQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD+RIZQmpKewCum8E6vWNr7t7u3vjhXZWW/HfGAvJWAEAIgXW5DGRFb/pVFFD9+M81syb46TRiVIpOyZjTNrWcdnAM="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.0.tgz_1464673949411_0.8832829571329057"},"directories":{}},"0.2.1":{"name":"teambition-sdk","version":"0.2.1","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","browser":"dist/bundle/tbsdk.umd.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && npm run build_all && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_async":"rm -rf dist/bundle/tbsdk.async.js && ./node_modules/.bin/tsc ./src/AsyncApp.ts    -m commonjs --outDir dist/async    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.async.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/rx.ts && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_async","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"engine.io-client":"^1.6.9","es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","rxjs":"^5.0.0-beta.8","rxjs-es":"^5.0.0-beta.8","snapper-consumer":"github:teambition/snapper-consumer","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","fetch-mock":"^4.5.0","istanbul":"^0.4.3","mocha":"^2.3.4","mocha-phantomjs":"^4.0.2","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.7.3","tslint":"^3.10.2","typescript":"^1.8.10","typings":"^1.0.4"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"7e16730927dc2e83a3e3700ec802a48a17cf12ca","_id":"teambition-sdk@0.2.1","_shasum":"547e3117a8a3b4e4d34afaac352c28cf20e986b4","_from":".","_npmVersion":"2.15.5","_nodeVersion":"4.4.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"547e3117a8a3b4e4d34afaac352c28cf20e986b4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.1.tgz","integrity":"sha512-jb2njGhKvOpncZ1XvADkYjp3f35B5mb4dDmLRBok6Q1+HHmkEOLHSLp3FvbvzEehp+JIgZoAWsiOVFJZY8qKog==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDMQ7LZFs9qn0jRy2lrUwGCoVCRzXjwxXQmuGD1MoPWeAIhAM5ai72/mTcmUqCcOec1K2vCGgmml5awJX9Bph48+9D1"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.1.tgz_1464937279386_0.04641942027956247"},"directories":{}},"0.2.2":{"name":"teambition-sdk","version":"0.2.2","description":"Front-End SDK for Teambition","main":"dist/bundle/tbsdk.umd.js","jsnext:main":"dist/es6/app.js","browser":"dist/bundle/tbsdk.umd.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/rx.ts && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"engine.io-client":"^1.6.9","es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","rxjs":"^5.0.0-beta.9","rxjs-es":"^5.0.0-beta.9","snapper-consumer":"github:teambition/snapper-consumer","symbol-observable":"^0.2.4","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","fetch-mock":"^4.5.0","istanbul":"^0.4.3","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.7.3","tslint":"^3.12.1","typescript":"^1.8.10","typings":"^1.0.4"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"07bc8bb01b719ed7b8f630eb85bb804b5c1f9505","_id":"teambition-sdk@0.2.2","_shasum":"1f31881b5540838429e8cc80246953f85e2307b5","_from":".","_npmVersion":"2.15.8","_nodeVersion":"4.4.7","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"1f31881b5540838429e8cc80246953f85e2307b5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.2.tgz","integrity":"sha512-AgSbgNf+CZzHvqWSBc2cSGNZTeoDEJxF4m0/gKCQ9FeDFteV79wSPS+vpja+L1Q+y7ZlmhrHF4kccXvoSdJ/rg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCHa8k2nSzy80IQCIbQJu3sSIyOj+nih7GtKFJOLVse1gIhAM0eFQp9tzv676f4GDhk/3BO9OwZWX4ksixgKF3NPfEB"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.2.tgz_1467277605083_0.8755628259386867"},"directories":{}},"0.2.3":{"name":"teambition-sdk","version":"0.2.3","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","browser":"dist/bundle/tbsdk.umd.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/rx.ts && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"engine.io-client":"^1.6.9","es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","rxjs":"^5.0.0-beta.9","rxjs-es":"^5.0.0-beta.9","snapper-consumer":"github:teambition/snapper-consumer","symbol-observable":"^0.2.4","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","fetch-mock":"^4.5.0","istanbul":"^0.4.3","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.7.3","tslint":"^3.12.1","typescript":"^1.8.10","typings":"^1.0.4"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"ea1371bfd4024ba04c8b2e8adddaafc2af16e0d1","_id":"teambition-sdk@0.2.3","_shasum":"77532bbaa979934fabd49f6c41408fe2348753d5","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"77532bbaa979934fabd49f6c41408fe2348753d5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.3.tgz","integrity":"sha512-T+PojSTDOAh2Ls9EfLEdMRGyzQDd+lZTiqTsQ9yY6zZ93cP0flq8oxIpIWSRc3jNwFIljjZ7xB9LbrLbDDGEkw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDt15KHtaw/N+5NTSHrHw3xOyU10LphLkzHzcYHgbDp9QIhANiOkSoKXZjavMb3cNl9TNU7RnKz0rpGfFAzVXqNTWYq"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.3.tgz_1467627725899_0.003971393220126629"},"directories":{}},"0.2.4":{"name":"teambition-sdk","version":"0.2.4","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/rx.ts && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && cp ./dist/mock-cjs/** ./.tmp/mock && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"engine.io-client":"^1.6.9","es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","rxjs":"^5.0.0-beta.9","rxjs-es":"^5.0.0-beta.9","snapper-consumer":"github:teambition/snapper-consumer","symbol-observable":"^0.2.4","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","fetch-mock":"^4.5.0","istanbul":"^0.4.3","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.7.3","tslint":"^3.12.1","typescript":"^1.8.10","typings":"^1.0.4"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"7c2edf476bd4ac53e2f7ca70bebe96224ab0c041","_id":"teambition-sdk@0.2.4","_shasum":"1d744c595b77721bbe9aa929eb35032fa0a4a9ad","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"1d744c595b77721bbe9aa929eb35032fa0a4a9ad","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.4.tgz","integrity":"sha512-kf9qDpPfywH8oLE2Ymjj9bolDhaXcHoyXKR3u8Mg3T+Q3Vcx/ddbwm/yB0CmkLQRD2zh3wiWe2euPytaRcu+HA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD4oOOF2VlfNLsi7mK26p0z+59w8vBJdvcVaqvx/j78IAIhALIiyJIUxLb+0a5NgIF4RTJluptgOkZkV6x/lvzJK98l"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.4.tgz_1467793007739_0.3649476144928485"},"directories":{}},"0.2.5":{"name":"teambition-sdk","version":"0.2.5","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"engine.io-client":"^1.6.9","es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","rxjs":"^5.0.0-beta.10","rxjs-es":"^5.0.0-beta.10","snapper-consumer":"github:teambition/snapper-consumer","symbol-observable":"^1.0.1","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","fetch-mock":"^4.5.0","istanbul":"^0.4.3","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.7.3","tslint":"^3.12.1","typescript":"^1.8.10","typings":"^1.0.4"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"769951c449bbfd4bc9b25259c006e26090c3a19e","_id":"teambition-sdk@0.2.5","_shasum":"154c6d74ee1fb291c4760baa617049cf5c93dbe1","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"154c6d74ee1fb291c4760baa617049cf5c93dbe1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.5.tgz","integrity":"sha512-G82AbpzmSoayj/g1WNsV+3BwcseX+Gx3x4V223LcJpTNqoekS1nnNPeq4QoRL0+ZoPbyq2lX0qwC2E2ModLmyA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCVbwuHn3N7RGla4farKAf/3cu5gsz+9zlB9fR1xb6yegIhAMVCglRsAf9nTwhQrRS9fOzTeq0E35pkpggaVHFd/TM9"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.5.tgz_1468147443371_0.9175757670309395"},"directories":{}},"0.2.6":{"name":"teambition-sdk","version":"0.2.6","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"engine.io-client":"^1.6.9","es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","rxjs":"^5.0.0-beta.10","rxjs-es":"^5.0.0-beta.10","snapper-consumer":"github:teambition/snapper-consumer","symbol-observable":"^1.0.1","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","fetch-mock":"^4.5.0","istanbul":"^0.4.3","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.7.3","tslint":"^3.12.1","typescript":"^1.8.10","typings":"^1.0.4"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"006e154daf65bb29da735c1b924864e433ec3259","_id":"teambition-sdk@0.2.6","_shasum":"0e1bcd4ab87dd80dc444cbcc7ba8a15496608e5d","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"0e1bcd4ab87dd80dc444cbcc7ba8a15496608e5d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.6.tgz","integrity":"sha512-ZCGtHzdAG+PWRdEFj6bSkJiTdOXRvZzoCvegcJ3Mk6Uc4GkphXr3TvDVLQl7h7eVxfWsJAIg2i6IjTs8cBpPXQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFECVvUQi1u2P9B+D31VC9BZKkxpeMcVQq20wWkZFJw/AiEAqSjUrgetvww6geLcvLbcJZSBf7138FdZSgPzDS0FL2A="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.6.tgz_1468255053101_0.9940894234459847"},"directories":{}},"0.2.7":{"name":"teambition-sdk","version":"0.2.7","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"engine.io-client":"^1.6.9","es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","rxjs":"^5.0.0-beta.10","rxjs-es":"^5.0.0-beta.10","snapper-consumer":"github:teambition/snapper-consumer","symbol-observable":"^1.0.1","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","fetch-mock":"^4.5.0","istanbul":"^0.4.3","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.7.3","tslint":"^3.12.1","typescript":"^1.8.10","typings":"^1.0.4"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"6a1c9724e281abced3bba67e695d5ccf4d44005d","_id":"teambition-sdk@0.2.7","_shasum":"cfaef9a8468ecc15a52696d514766b52d477314d","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"cfaef9a8468ecc15a52696d514766b52d477314d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.7.tgz","integrity":"sha512-daHUVKVk8fKsPXBsOgzZqlReCS1mwKt9P7C9IfHQJ6tDBGIPUGq51uh3H3ktYWDRDQuCkoo7OZTY0xS+dozOLA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJlnQcUONIWJuOjZtbyRGnapJ8pXv6FGu7Vbfq+28bcwIhAJmdoqv/3RklEdgaTIZM354H8SRsWgcb5ksHeJsnOIpj"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.7.tgz_1468255329890_0.6289945624303073"},"directories":{}},"0.2.8":{"name":"teambition-sdk","version":"0.2.8","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"engine.io-client":"^1.6.9","es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","rxjs":"^5.0.0-beta.10","rxjs-es":"^5.0.0-beta.10","snapper-consumer":"github:teambition/snapper-consumer","symbol-observable":"^1.0.1","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","fetch-mock":"^4.5.0","istanbul":"^0.4.3","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.7.3","tslint":"^3.12.1","typescript":"^1.8.10","typings":"^1.0.4"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"ff3aeeafd9ab81369cfa382db7dc9041ea1efdf9","_id":"teambition-sdk@0.2.8","_shasum":"78d2ebf822acfc93754a60e689a8989e3f6202e5","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"78d2ebf822acfc93754a60e689a8989e3f6202e5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.8.tgz","integrity":"sha512-1uYnLtXUpX/9oSI8jmsVQb0m1o6hoUAklQSe2HXCg3YkUXL2qemlwNyrJ3fLQAGXjIaSztux5RiHQoepihPdlA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDBQJdWLUO0Ij4zYB4pI5CUwnyu98OC8qTbfs/3gxKYfAiBCnGMsES/MAgAJrkjiV4kBJ7VoqkHunAHxYCmdU7/SOw=="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.8.tgz_1468379382494_0.7602831611875445"},"directories":{}},"0.2.9":{"name":"teambition-sdk","version":"0.2.9","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"engine.io-client":"^1.6.9","es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","rxjs":"^5.0.0-beta.10","rxjs-es":"^5.0.0-beta.10","snapper-consumer":"github:teambition/snapper-consumer","symbol-observable":"^1.0.1","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","fetch-mock":"^4.5.0","istanbul":"^0.4.3","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.7.3","tslint":"^3.12.1","typescript":"^1.8.10","typings":"^1.0.4"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"1f5acb194feaa46ba5a2c0b7000a77b797425e1a","_id":"teambition-sdk@0.2.9","_shasum":"445b230be745a317f43ac88841269a07fb2f6859","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"445b230be745a317f43ac88841269a07fb2f6859","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.9.tgz","integrity":"sha512-TCXXqFwEwd9znrLtTmelVr4ZujqURZ3UDLb842k2m6+M99B+Iyq+uuGq/n/SmJFpGHOe/F4Mfme+N0OeEJj+4w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEik4ra3FGQuRfD4VERjqoBbthKgaar5ci0nz7A6fyftAiBuZtlaJTUn2FSUEtslDJMV5WCXpK3s/u7g7EjgfjL3nQ=="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.9.tgz_1468480110359_0.7176761897280812"},"directories":{}},"0.2.10":{"name":"teambition-sdk","version":"0.2.10","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","symbol-observable":"^1.0.1","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","fetch-mock":"^4.5.0","istanbul":"^0.4.3","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^1.8.10","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"b1eed66e0a55c8c59cc36f62f2471c9dc102e8a3","_id":"teambition-sdk@0.2.10","_shasum":"a487d0a8ec5dfc9423f83ea0cc766e79c2f2257f","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"a487d0a8ec5dfc9423f83ea0cc766e79c2f2257f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.10.tgz","integrity":"sha512-wfU7QfLDTM2jWhXyGd7tbf/IgUQA5XKndM7wYWGDLrVS9v57N39myYe4qrd/NM6XHbNXkaO+p9ro4OyM4skfUw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGZJi4gC8IZ9f9COR3dCsDdnjaCuTz5Po85KHAvcj0DNAiEA4pSWbn787rvTw1EumDS6cxJguVuCigBV8tqemTQcjVI="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.10.tgz_1468580200702_0.23243488231673837"},"directories":{}},"0.2.11":{"name":"teambition-sdk","version":"0.2.11","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","symbol-observable":"^1.0.1","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","fetch-mock":"^4.5.0","istanbul":"^0.4.3","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^1.8.10","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"8a325fa79199bb805f7f5340522eedcdbaa91091","_id":"teambition-sdk@0.2.11","_shasum":"6d8b396c0103812b3903588f62d6117b71686111","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"6d8b396c0103812b3903588f62d6117b71686111","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.11.tgz","integrity":"sha512-owZjZ+pefiMok74JMcp+G1IKRN0ImwcjK+HgNI8sluq97S4Bgx2cuZPOM5XhM5M3WuL8Gw/wM1B59noncBxjoA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDDab42lIqeJ2DPbn3neOBaDsGYHXkU3alG72st+E4u4wIgPhHIeWmj1ifStgxhgXFPgcTBx+3Xwh7bdnvr5DYfkCY="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.11.tgz_1468725300918_0.05334045994095504"},"directories":{}},"0.2.12":{"name":"teambition-sdk","version":"0.2.12","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","symbol-observable":"^1.0.1","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","snapper-consumer":"github:teambition/snapper-consumer","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^1.8.10","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"1813d3e62158215aeb5fb7fd36471bce39b48eba","_id":"teambition-sdk@0.2.12","_shasum":"7cea501967a9240493942956fd5927d516b759ce","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"7cea501967a9240493942956fd5927d516b759ce","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.12.tgz","integrity":"sha512-Yi3a/sceVrFfXkesp8XoM6ZXwUHTN4XSJAkdKNpMRphs0ucyAExSdx9st5ZxVXvuh4jyg5QPMOP5TaieTmAnbA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8x1JT0LTsn5hvJs0mpsSKAJcPJQ19o/wFhsHxWPeVqwIgEOP06/+8JLkLvD9+wLosnPsq0lepfivDnpy7HswbkIM="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.12.tgz_1468725509884_0.8515822875779122"},"directories":{}},"0.2.13":{"name":"teambition-sdk","version":"0.2.13","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","snapper-consumer":"^1.2.0","symbol-observable":"^1.0.1","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^1.8.10","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"cae3fe49131f0e7e4c1702b2d5b0d6f914179747","_id":"teambition-sdk@0.2.13","_shasum":"25179f37bc7d9ed7a18d7309ab9b3fe968329491","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"25179f37bc7d9ed7a18d7309ab9b3fe968329491","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.13.tgz","integrity":"sha512-jsiwZsvyU138itt20sIxJpsmE9PZZ6nnJPrnCOU/rU8WbaAt2ur2HRqWDbPyRSm9siBGgrbRiVjxSmwOkv69RA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCvRJinmFTWVeO5+3cPlkaeZ71XyCoFMy3dV5ila+cK7AIgW4fxxhO3xTIO3Uvdxx5uNjGUM0UbQbW3lmjS4YatfdQ="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.13.tgz_1468920401483_0.23625947488471866"},"directories":{}},"0.2.14":{"name":"teambition-sdk","version":"0.2.14","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js       --sourcemap --sourceRoot test/unit --target ES5       --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","snapper-consumer":"^1.2.0","symbol-observable":"^1.0.1","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^1.8.10","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"8a6253cff8665a61fda7cd82b9c1860107e047d8","_id":"teambition-sdk@0.2.14","_shasum":"00eab041c21022802e0238d1f99009b3cda6aa8f","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"00eab041c21022802e0238d1f99009b3cda6aa8f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.14.tgz","integrity":"sha512-L1bfoPm+caXzw/rD7/LznUHYhbtfJCfGun6hw1X81jxemoZircAqrVvmj8BPkXvPRUEpapwq93OCNiCWbWDsXw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEqhayCxli2Kuh56sQu7rC8WHeiglKJvApXgvkh+VZNtAiBEZuwOAxcd5waRMAPqAYr4+gMHZY1GML05LULzdqqcbg=="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.14.tgz_1469012576343_0.2778987481724471"},"directories":{}},"0.2.15":{"name":"teambition-sdk","version":"0.2.15","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","snapper-consumer":"^1.2.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^1.8.10","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"77868e22b55092b641c5d6a20670ff462ba9312b","_id":"teambition-sdk@0.2.15","_shasum":"591e9e1bc6e1960d7f88624d55231bbbb5b85a8d","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"591e9e1bc6e1960d7f88624d55231bbbb5b85a8d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.15.tgz","integrity":"sha512-jjQFuqAu7VT6NT3wvsU0vWaFvLOTG7a6FX7dBMsZgphS9Y7AIamODe1q96hqHcg1ez+Io8TLnVIpIDfzoywxVw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCQ9f0CoFIe6nPEBhSqbCSOvjUOmJC3fH8SQv6YnA0eaAIgIDtgU2F718sAbbIsc2X9fxbyGP5tRZojOSv0YLqozM0="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.15.tgz_1469180972105_0.30259029450826347"},"directories":{}},"0.2.16":{"name":"teambition-sdk","version":"0.2.16","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","snapper-consumer":"^1.2.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^1.8.10","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"701a34a9d4f052dbf5365a2853de7dfb5b70b5a3","_id":"teambition-sdk@0.2.16","_shasum":"53eb11346fe4d1192741b5e9126e87d5babf47c5","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"53eb11346fe4d1192741b5e9126e87d5babf47c5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.16.tgz","integrity":"sha512-7eaFZAxPUpcBXLYPeqD8LTCpvXgOQsIzAW/94hTC4LvpNzqe4Xqu1bI9V+cb9wig5hA9wYrumLYPTfQN3MOojQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEM+bVR4FYWvCbmrf/P8E+7M54A6WNn+Cu3SAL7gfxYsAiEA+H4MuJlz2Unzq/cgEYaRsUd0VjnfA0/ok0dMo8XIT0s="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.16.tgz_1469501071732_0.32811813056468964"},"directories":{}},"0.2.17":{"name":"teambition-sdk","version":"0.2.17","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","snapper-consumer":"^1.2.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^1.8.10","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"fdd615f1f05cfe3d6a65b6fcbcbcf6f0c7ff335c","_id":"teambition-sdk@0.2.17","_shasum":"178f14de4dec8fac87ba3b4cef36c1ce487be15a","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"178f14de4dec8fac87ba3b4cef36c1ce487be15a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.17.tgz","integrity":"sha512-TKVBoqq1x4VwkPr3Ej7aXw2T+TTLt3nFdMiBc0ASwQ9ICIriwRPra/a65KSrQ024DuOAwN54D0uxawjOQXIoYQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDWgjcFIQ/i1+XV/ZyoSSVl9fErKrUK+/lqy+UnX91a3gIgLFH2bklVwzLOPsDVTjohaM5arD4+XLTU0eYdIYOgJVM="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.17.tgz_1469502596104_0.9222214345354587"},"directories":{}},"0.2.18":{"name":"teambition-sdk","version":"0.2.18","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","snapper-consumer":"^1.2.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^1.8.10","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"9f2a0b21b40fe5370cc4b952f7cca4eaf16306b3","_id":"teambition-sdk@0.2.18","_shasum":"77716d390595e3236ce8658430a332d81bb39710","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"77716d390595e3236ce8658430a332d81bb39710","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.18.tgz","integrity":"sha512-vh0w/6OCo+lKJpOI7AHXy8acH8sK9ODdPvZq3gRJj9wAp7dOevALhyr7/gFpxQZcWzXu/5NS0oEm/yhjWRU3rA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCuQQF/1twVgl3uOR3r6Sd6b6hqluDM2TR8wGUm+BrGZQIhALy+iEzCmYPIyfwRmz1XlLoQQnglMiTTVgPzPJVFSg3J"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.18.tgz_1469627627074_0.17571125435642898"},"directories":{}},"0.2.19":{"name":"teambition-sdk","version":"0.2.19","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","snapper-consumer":"^1.2.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^1.8.10","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"931782d8bbf08e5b98ea583ac259aabe56f25021","_id":"teambition-sdk@0.2.19","_shasum":"2083b7c800a461bfc912e4045e9d3e88120721d4","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"2083b7c800a461bfc912e4045e9d3e88120721d4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.19.tgz","integrity":"sha512-mele41/gj64Mez2uk0Ejlfl+adRRZlGpO/DDskPM8SF6yQt1JhDSOrFHEh1uEHuVU6mAIsM0LLOmUAHlahQfIg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAu8vNZ5UObkxIokIWjdp3Awf+Sy41iCG7ofjXukuyuQAiEA2IRLOV3eLGBjrZ9FpbAga+ZLLpiE9Hq7O+Z/agOYB/M="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.19.tgz_1469628662998_0.013815258396789432"},"directories":{}},"0.2.20":{"name":"teambition-sdk","version":"0.2.20","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && ./node_modules/.bin/tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && ./node_modules/.bin/tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js   && ./node_modules/.bin/tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && ./node_modules/.bin/tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && ./node_modules/.bin/tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ./node_modules/.bin/ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ./node_modules/.bin/ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && ./node_modules/.bin/tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ./node_modules/.bin/ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && ./node_modules/.bin/tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && ./node_modules/.bin/tslint ./mock/**/*.ts && ./node_modules/.bin/tslint ./test/unit/**/*.ts","cover":"npm run build_test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ./node_modules/.bin/ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","snapper-consumer":"^1.2.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^1.8.10","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"041af7dbb9878d14f89d5a6bfd6360703a953480","_id":"teambition-sdk@0.2.20","_shasum":"92b3f1cdbfcee7e8bcafc396044a334814462362","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"92b3f1cdbfcee7e8bcafc396044a334814462362","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.20.tgz","integrity":"sha512-+tn+el4cSSffAMUP3fWo5bT7kCdm277+Y3iMASamfz1vkpnXiBMiCmbDQRmdAIi35u0AEcztKU1IkZtDVHlKIQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD4Dua9KtXnEMXeouF+XFQvZgJiClO0p/eGUP38Gc3Y0AIhAJFIqCX/86+kc2HfOFhqMD5dPcVLWF4xId85FMq9byfn"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.20.tgz_1469635085148_0.578622784698382"},"directories":{}},"0.2.21":{"name":"teambition-sdk","version":"0.2.21","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs   && tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts     -m commonjs --outDir dist/cjs      --sourcemap --sourceRoot src       --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6   && tsc tools/build/target-es6.d.ts src/app.ts -m es2015   --outDir dist/es6      --sourcemap --sourceRoot src       --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js   && tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e                                  --sourcemap --sourceRoot test/e2e  --target ES2015    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts    -m commonjs --outDir dist/socket    --sourcemap --sourceRoot src       --target ES5    --diagnostics --pretty                                                               --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc tools/build/test.d.ts test/unit/app.ts -m commonjs --outDir spec-js                           --sourcemap --sourceRoot test       --target ES5      --diagnostics --pretty                                     --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts                      -m es2015   --outDir dist/mock-es6 --sourcemap --sourceRoot mock      --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock      --target ES5    -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts && tslint ./mock/**/*.ts && tslint ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","prepublish":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","snapper-consumer":"^1.2.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^1.8.10","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"08602bcd1b7ffba2619e372fb7c8552f6624933b","_id":"teambition-sdk@0.2.21","_shasum":"8f940a3ea73fda442640f7987477f408fd601841","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"8f940a3ea73fda442640f7987477f408fd601841","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.2.21.tgz","integrity":"sha512-7pJeDM5MI2rwd8m5/NykuXQcbRFGACSvBMv175BPHW6HIePZ2OxLRa8wg2TQrnKEaV/oXNG7FNMGp5yj/TOCuw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCyIvAY+HlWXLu1gZ+1Mhi0Liu7xwNKyu/KN9hH1JnAkQIhAL2ZdEw9Rh83KNqJqX94uTAxDyNJx2OxkBUeQ1tzsDr4"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.2.21.tgz_1469781752808_0.006400563521310687"},"directories":{}},"0.3.0":{"name":"teambition-sdk","version":"0.3.0","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","es6-collections":"^0.5.6","es6-promise":"^3.1.2","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","snapper-consumer":"^1.2.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"2.4.0","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^2.0.0","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"08e589e586b3a07e25bf43f2c8ca95699b13ba76","_id":"teambition-sdk@0.3.0","_shasum":"5d631f9d6f60662d2d7b1345ebc318d036f57847","_from":".","_npmVersion":"3.9.5","_nodeVersion":"6.2.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"5d631f9d6f60662d2d7b1345ebc318d036f57847","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.3.0.tgz","integrity":"sha512-8MB82THH3rvNi9bzmlsgQOiu+oF5km+aSBaI9xsymX29U3+EsbDZ6H0NA/71/hJEp1eTss02mXHSf5eizviLLw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBqXkd357J7zl+4jFebTqYbCnfiLofWdX71e54WfTi7LAiEAr7C+f0SirpLCOmA0ZfiHAGDdOUy7y394Zm8Kx38iYUs="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.3.0.tgz_1470316144988_0.41953178541734815"},"directories":{}},"0.3.1":{"name":"teambition-sdk","version":"0.3.1","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","snapper-consumer":"^1.3.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^2.0.0","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"616c4daf6e52f707e2f63e16f145e7d5fc311304","_id":"teambition-sdk@0.3.1","_shasum":"128053c1d2a1b530b063cc46410d1a6f5d21d0a4","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.3.1","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"128053c1d2a1b530b063cc46410d1a6f5d21d0a4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.3.1.tgz","integrity":"sha512-M9GyRmMMnGqgw9e1H/+y8npzqVU4P0BQKGb3/pIlgf/3oS8zaFMzqdKH5SoqReB1t2no+N8ssVdJOAWczuy91A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCwd7n9P7RVLZmMKnVwQdu9TbtpRcBjCKCSAnoCB+6ZIgIgQvXqtlc4AO73ATzCK46QoEZ0huJWYhOf3dN3k8s57gI="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.3.1.tgz_1470726252145_0.6875622030347586"},"directories":{}},"0.3.2":{"name":"teambition-sdk","version":"0.3.2","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.10","snapper-consumer":"^1.3.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^2.0.0","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"5194975d661fa21516f94ec7ce839b18ee39a3ae","_id":"teambition-sdk@0.3.2","_shasum":"a56224ab39eb79fb0e9ed7062deb69ef2c79107b","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.3.1","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"a56224ab39eb79fb0e9ed7062deb69ef2c79107b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.3.2.tgz","integrity":"sha512-6oisR10ewJDHGmvnNI3f/IOTYYokWsntyRkwbeu00iHeqSFw0ypI1EqHlMe42+bxRdIMg2cT1bmwQETWGPkQxg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCzLZwMfcIGt6gl2KmMbLe5veCIoxQiWX0qeMLKCql4RAIgIHggk+RwByxji9zVaLcHGk0UUnSjEAu8UMCckNTtiHg="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.3.2.tgz_1470741669445_0.6362235134001821"},"directories":{}},"0.3.3":{"name":"teambition-sdk","version":"0.3.3","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.11","snapper-consumer":"^1.3.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^2.0.0","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"bc79699bc2c478cbb032e0041651f0d3e6642504","_id":"teambition-sdk@0.3.3","_shasum":"49d45e52edfd42b2ff62f6569dd3472895e3efd7","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.3.1","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"49d45e52edfd42b2ff62f6569dd3472895e3efd7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.3.3.tgz","integrity":"sha512-DHeQIlX2AeFwo5WUvtSsHE7GBz6WXcLmb64for9pVngariwh0HovWK3b4/hzUbA+Vir28949wnAiDd2PDSB98g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBfVvtbuiEM1Vu7AxtEuATM8dG4DtO0rAOqkt5eSM2FVAiEA/rU+KxWwvBTn8UNSKV1H4Qa34irJJglq9JnGK8WzqRU="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.3.3.tgz_1471350057417_0.5167267099022865"},"directories":{}},"0.3.4":{"name":"teambition-sdk","version":"0.3.4","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.11","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^2.0.0","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"b4cb3d06ba1276de590de85d3c339d09a30535c3","_id":"teambition-sdk@0.3.4","_shasum":"ca58615180155d2be046233588dbfe28988bd4cd","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.3.1","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"ca58615180155d2be046233588dbfe28988bd4cd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.3.4.tgz","integrity":"sha512-Yzimox2HFEQrjBQfMsifOONQhISu5crUcTeHIciEyVtVbF5bIaQaDz8UQSHxNQQQcNKBg6abogwTVX7G45W1VQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAv3P7LK5HjlayE3DwWiJVlQP6gCVWQxX/w0OpCVUp/8AiEAoiLgLHZD7cS2KQTJXEWd0EPmYuUqJImXlzMvtSKxDow="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.3.4.tgz_1471350194107_0.9758626658003777"},"directories":{}},"0.3.5":{"name":"teambition-sdk","version":"0.3.5","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.11","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^2.0.0","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"87f81e477b458eed9f690a113e83fd34d48cc293","_id":"teambition-sdk@0.3.5","_shasum":"67fc7a3dc2953b3f87cffcb097566e77fe5e4bca","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.3.1","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"67fc7a3dc2953b3f87cffcb097566e77fe5e4bca","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.3.5.tgz","integrity":"sha512-oJ7JuN0wAaBupL23GJsgz89biia7H0xQ/4/tejvS/EUU7bnAkhVZfAgD+M6w0NNiI8Lq2Dkk0hjgGGGSNo3DAA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIQDDaltDolH4uyeO+LM3iJOp1L2WQpItek1VNoDkvKXVSwIfVYa4ZAC2SXD1yTfo4iK5U/ijKMRDF9rIinu4qoSnng=="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.3.5.tgz_1471419390080_0.9693970237858593"},"directories":{}},"0.3.6":{"name":"teambition-sdk","version":"0.3.6","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.11","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^2.0.0","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"5c18920d3052f57bf91d887fa8825b263416e0d1","_id":"teambition-sdk@0.3.6","_shasum":"dc3ac9101a14187707add1930a581a476e292ec7","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.4.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"dc3ac9101a14187707add1930a581a476e292ec7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.3.6.tgz","integrity":"sha512-n7bXCl5Wpq6anDi5QXTazG9SdAxPjgpRsXzp4/WegA/OFVsE22sEAH+I7vEBZLuGc3EQKkLV0bmDbThs+nf5ow==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD/iHyPWJnMdKG6r/lHX6y6jRIntrCGMGMpbARref2AewIhAOuNyatRTRrFYgtCbvE15ey95L+YqFuCL7L/QQfGlCb3"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.3.6.tgz_1471604632603_0.0752391021233052"},"directories":{}},"0.3.7":{"name":"teambition-sdk","version":"0.3.7","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.11","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.0","symbol-observable":"^1.0.1","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^4.5.0","istanbul":"^0.4.3","jsonrpc-lite":"^1.2.1","mocha":"^2.3.4","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.26.3","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^2.2.1","rollup-plugin-node-resolve":"^1.5.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^0.9.3","tslint":"^3.13.0","typescript":"^2.0.0","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"20cdf17add1e0732e8d4e715b3980cd7ca5ab850","_id":"teambition-sdk@0.3.7","_shasum":"c25e6b3a63268d6834bde510209b3925bbd4e19c","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.4.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"c25e6b3a63268d6834bde510209b3925bbd4e19c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.3.7.tgz","integrity":"sha512-YkbXQjYOTesLmUk/MWMRXYtdRrHWHVKAOFy0wu2Lv9rqnF2u6Y8B//vl31KR01ypmNGd6hio7oWkNre1BOqG5w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAeWMjBIL/ZiNf7ClKC9bybdawGJV5NSK3KcdK5znGQUAiEAidbQoT/nf2BmTMyIrboFExL3g6bhyZhZd3wYtHSvQjg="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.3.7.tgz_1472013647547_0.6366133221890777"},"directories":{}},"0.4.0-alpha.1":{"name":"teambition-sdk","version":"0.4.0-alpha.1","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","ts_test":"mocha --compilers ts:ts-node/register,tsx:ts-node/register test/unit/app.ts","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.11","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^5.1.1","istanbul":"^0.4.5","jsonrpc-lite":"^1.2.1","mocha":"^3.0.2","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.34.10","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^3.3.1","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^1.3.0","tslint":"^3.14.0","typescript":"^2.0.0","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"f00ed0ef28c0bbe65402279a4f4952d948e1c547","_id":"teambition-sdk@0.4.0-alpha.1","_shasum":"29038f436b7b9a4b1d4eef4d9fb6ee0b3362aa7a","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.4.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"29038f436b7b9a4b1d4eef4d9fb6ee0b3362aa7a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.4.0-alpha.1.tgz","integrity":"sha512-Y++8ODvU9BTJSRUC9JWeew1r5EliMwuVh3vZdgbw0dhlMOHg4VdXAdER02cflHCPz9QOEgemyaAo09II1L5M/A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCr7nXmB9DAd74P2u5QPyF2evoj2afZ0jnLlHTAMesubgIgF6EVvBLoBgp7vOb/syCRDAFV8bbL8zdwhZ8ufNw36FQ="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.4.0-alpha.1.tgz_1472465478735_0.47375608840957284"},"directories":{}},"0.4.0-alpha.2":{"name":"teambition-sdk","version":"0.4.0-alpha.2","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","ts_test":"mocha --compilers ts:ts-node/register,tsx:ts-node/register test/unit/app.ts","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.11","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^5.1.1","istanbul":"^0.4.5","jsonrpc-lite":"^1.2.1","mocha":"^3.0.2","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.34.10","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^3.3.1","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^1.3.0","tslint":"^3.14.0","typescript":"^2.0.0","typings":"^1.3.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"0cb1c4814435783a405ce51ec2a9383db3a4e1e0","_id":"teambition-sdk@0.4.0-alpha.2","_shasum":"24502a5b96e1d26cb4220d8e1c266fac04b78221","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.4.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"24502a5b96e1d26cb4220d8e1c266fac04b78221","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.4.0-alpha.2.tgz","integrity":"sha512-r+9+vMeoJuZkqSmrzETLbZPEyYxiZOnjA4g1YQQyB0Gr805AxgzLZ79AcoFCV33hTpMXx1zfuE28GPwtb/mIbA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCX33tuGT2B2ccqgtuEx3YmN1pnNGi1lULdSyED3w71CgIhAJWXs1W/oZyEvgiABSoasy/SSHmlvB5DwupsnyWPTy4G"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.4.0-alpha.2.tgz_1472535190269_0.9788970681838691"},"directories":{}},"0.4.0-alpha.3":{"name":"teambition-sdk","version":"0.4.0-alpha.3","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","ts_test":"mocha --compilers ts:ts-node/register,tsx:ts-node/register test/unit/app.ts","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.11","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^5.1.1","istanbul":"^0.4.5","jsonrpc-lite":"^1.2.1","mocha":"^3.0.2","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.34.11","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^3.3.1","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^1.3.0","tslint":"^3.15.1","typescript":"^2.0.0","typings":"^1.3.3"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"46ceed7e80c3c40614137c8c7b7b421cc5701977","_id":"teambition-sdk@0.4.0-alpha.3","_shasum":"b021c4fb0537036368ce63f87f447b28a1bad357","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.4.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"b021c4fb0537036368ce63f87f447b28a1bad357","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.4.0-alpha.3.tgz","integrity":"sha512-mHG+dvwjhgf0JHhm2rXG1WDZcSdNPsEI+1XVbuAr0H9dsKHwbTmcCPTFJnk9R55vLGVfLYbmVF8p3hDIYgjTkw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDE8ib8X3LTiNLWgZZ5GesNsmydqLYRsRLOIak18IdqVQIgO7gIC4kyKwG7NRlBLJDupo3dwh78CJsnDcvs1U5nrJg="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.4.0-alpha.3.tgz_1472701565373_0.5380276050418615"},"directories":{}},"0.4.0-alpha.4":{"name":"teambition-sdk","version":"0.4.0-alpha.4","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","ts_test":"mocha --compilers ts:ts-node/register,tsx:ts-node/register test/unit/app.ts","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.11","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^5.1.1","istanbul":"^0.4.5","jsonrpc-lite":"^1.2.1","mocha":"^3.0.2","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.34.12","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^3.3.1","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^1.3.0","tslint":"^3.15.1","typescript":"^2.0.2","typings":"^1.3.3"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"eeacd52ef2d56b4c9d4019b53eb77e0a5d4c34ba","_id":"teambition-sdk@0.4.0-alpha.4","_shasum":"d8dc5de64f55a13f91f691f52139f844e5078368","_from":".","_npmVersion":"3.10.5","_nodeVersion":"6.2.2","_npmUser":{"name":"aicest","email":"nomailthis@yahoo.com"},"dist":{"shasum":"d8dc5de64f55a13f91f691f52139f844e5078368","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.4.0-alpha.4.tgz","integrity":"sha512-tZ4bs7glpLWuWGkCG1kolTyMZi5NmeG5COif+lYur8iG3F82+KonnmGNKUQodU0z32uuTZyRCmhCUVs8RSj0DQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGq+F3mB2ZQkjz/gP8KRRzhypR7NoiR735mHhb3VMDslAiEA1Drr64drietfn2dUBGO6FhygxAnZp0FuOFafo16wV8Y="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.4.0-alpha.4.tgz_1472729114301_0.9470138261094689"},"directories":{}},"0.4.0-alpha.5":{"name":"teambition-sdk","version":"0.4.0-alpha.5","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","ts_test":"mocha --compilers ts:ts-node/register,tsx:ts-node/register test/unit/app.ts","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _mocha ./spec-js/test/unit/app.js -- -t 10000","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rxjs":"^5.0.0-beta.11","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^5.1.1","istanbul":"^0.4.5","jsonrpc-lite":"^1.2.1","mocha":"^3.0.2","moment":"^2.14.1","remap-istanbul":"^0.6.4","rollup":"^0.34.13","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^4.1.0","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","ts-node":"^1.3.0","tslint":"^3.15.1","typescript":"^2.0.2","typings":"^1.3.3"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"4843589a15c43cc3bea238881dd546ba17794286","_id":"teambition-sdk@0.4.0-alpha.5","_shasum":"8152a84554055a76fe7c10fbb35eb0194181c4a0","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.4.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"8152a84554055a76fe7c10fbb35eb0194181c4a0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.4.0-alpha.5.tgz","integrity":"sha512-2yGp4Ml2GljbxrleO4t2M9vv92GbgFEwz4ITPKLLgsGNK6lkJLRyWidcJTKR2H8o3E7mcfYMtiRHQRZw5Vobyg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCMrIlEAE4LOw1Z68DK2wGfdkc6iwKDV8etx3Rp+2MCeAIhAKNZpOEJ8d4YMuWSboRgXGoHZkOQyQzo3Znlh+EwBQ/t"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.4.0-alpha.5.tgz_1473674273490_0.9326320034451783"},"directories":{}},"0.4.0-alpha.6":{"name":"teambition-sdk","version":"0.4.0-alpha.6","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/target-es6.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES2015 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _tman ./spec-js/test/unit/app.js -- -t 10000 --mocha","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"babel-preset-es2015-rollup":"^1.1.1","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^5.1.1","istanbul":"^0.4.5","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","remap-istanbul":"^0.6.4","rollup":"^0.35.10","rollup-plugin-alias":"^1.2.0","rollup-plugin-babel":"^2.6.1","rollup-plugin-commonjs":"^4.1.0","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.4.5","ts-node":"^1.3.0","tslint":"^3.15.1","typescript":"^2.0.2","typings":"^1.3.3"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"16a6e9cd49d47e455720d9c26d7e1c7a1f1fa348","_id":"teambition-sdk@0.4.0-alpha.6","_shasum":"caee9621b7ab15a71a1a692d1d3143cd2a899636","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.4.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"caee9621b7ab15a71a1a692d1d3143cd2a899636","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.4.0-alpha.6.tgz","integrity":"sha512-LS+7LA6rOA4nnt9cchFwJ7afCmIdXgnrw12+4acdpP80TSdHqSCw0fG7poWKtebcG1/4CP4fYsRxtsAxGtg6Cw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHK0q/j9i4P61LZsMSPDlWx2b2ooxDfzaPjM+Jfl1urjAiAe01PdSv3SEnLP7nUC5qDMnwXcXCnCqCSVyhlmpnzjpg=="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.4.0-alpha.6.tgz_1473850604823_0.7865224932320416"},"directories":{}},"0.4.0-rc.0":{"name":"teambition-sdk","version":"0.4.0-rc.0","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution --skipLibCheck node -w","build_es6":"rm -rf dist/es6 && tsc tools/build/bundle.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --sourceRoot src --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts typings/globals/core-js/index.d.ts -m es2015 --outDir .tmp/e2e --sourcemap --sourceRoot test/e2e  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --sourceRoot src --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES2015 --diagnostics --pretty --sourcemap --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts typings/globals/core-js/index.d.ts -m es2015 --outDir dist/mock-es6 --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --sourceRoot mock --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _tman ./spec-js/test/unit/app.js -- -t 10000 --mocha","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^5.1.1","google-closure-compiler-js":"^20160916.0.0","istanbul":"^0.4.5","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","remap-istanbul":"^0.6.4","rollup":"^0.36.0","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.4.5","ts-node":"^1.3.0","tslint":"^3.15.1","typescript":"^2.0.2","typings":"^1.3.3"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"c661c6675416ff3abfd3f52ba287b03fee857fd8","_id":"teambition-sdk@0.4.0-rc.0","_shasum":"df27c6fd6dbf967853289f5b7dce0499b1fbaa35","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.6.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"df27c6fd6dbf967853289f5b7dce0499b1fbaa35","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.4.0-rc.0.tgz","integrity":"sha512-DyGqevXvfdv4XMDXa/MhSKqv8+ewqkY1H2AWu9XYrYQAO+FPxR9j7R/rHMwFDoHfwkgiN56866+fjwZg9UmJXA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD0nxluv5ooKRP86F1JgRZjVzT4afdP9dlHR5YrJMV4kgIhAPL5mP6ugpgGuA4b19Bc7ez6vF6qsEneP/I9sK3uCO+2"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.4.0-rc.0.tgz_1474629183555_0.02515142015181482"},"directories":{}},"0.4.0-rc.1":{"name":"teambition-sdk","version":"0.4.0-rc.1","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc tools/build/bundle.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts typings/globals/core-js/index.d.ts -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES2015 --diagnostics --pretty --sourcemap --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts typings/globals/core-js/index.d.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _tman ./spec-js/test/unit/app.js -- -t 10000 --mocha","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^5.1.1","google-closure-compiler-js":"^20160916.0.0","istanbul":"^0.4.5","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","remap-istanbul":"^0.6.4","rollup":"^0.36.0","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.3.0","tslint":"^3.15.1","typescript":"^2.0.2","typings":"^1.4.0"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"3cb6130ab98fc8f0105a749ee15815d69241ca53","_id":"teambition-sdk@0.4.0-rc.1","_shasum":"addb5ade41c70313eb59645a60e1a44f2cf36e1a","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.6.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"addb5ade41c70313eb59645a60e1a44f2cf36e1a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.4.0-rc.1.tgz","integrity":"sha512-olnDUE6S7UvE1Otdm/1wUwqVPiiHASe43YYskyg0Rk9fv2OhnReVpPO4cSYucNZtWQc+KIBDD1yz9T9tbZHiJw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDDnyw/0FbCTG3CQ+9fu3W2vvZjJXu0ZFrqGuGzjwxtyAIhANwovwDqjfFhGRS+Bbvr3dsi642AY6+9pWmBCMqwkyVW"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.4.0-rc.1.tgz_1475058044081_0.8847049607429653"},"directories":{}},"0.4.0-rc.2":{"name":"teambition-sdk","version":"0.4.0-rc.2","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc tools/build/bundle.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts typings/globals/core-js/index.d.ts -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES2015 --diagnostics --pretty --sourcemap --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts typings/globals/core-js/index.d.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _tman ./spec-js/test/unit/app.js -- -t 10000 --mocha","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^5.1.1","google-closure-compiler-js":"^20160916.0.0","istanbul":"^0.4.5","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","remap-istanbul":"^0.6.4","rollup":"^0.36.0","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.3.0","tslint":"^3.15.1","typescript":"^2.0.2","typings":"^1.4.0"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"704f6181d7689132c80c7af0ffaf4cff94757e8f","_id":"teambition-sdk@0.4.0-rc.2","_shasum":"7251ed43f1ed8045616caa7b137b3c273af3692a","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.5.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"7251ed43f1ed8045616caa7b137b3c273af3692a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.4.0-rc.2.tgz","integrity":"sha512-YqiNsjjyl2/VK+6rQtTDf2qj3QvUMxY4njhVlxfUXbxFcRyIRNoxnsoVRUKjXmO/U488Q1sQDyFh//W8wycslA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDy6fTwGS/yQXFRL85OHvFUZ3xlhPOQKcXbh4IOILzfTAIhAODq9h/CSMK7eFwiTQSLxT4hAHtj3wiGQGGhNFldYXbP"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.4.0-rc.2.tgz_1475128176692_0.8449152840767056"},"directories":{}},"0.4.0":{"name":"teambition-sdk","version":"0.4.0","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc tools/build/bundle.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts typings/globals/core-js/index.d.ts -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --outDir spec-js --target ES2015 --diagnostics --pretty --sourcemap --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts typings/index.d.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && istanbul cover _tman ./spec-js/test/unit/app.js -- -t 10000 --mocha","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.6.9","fetch-mock":"^5.1.1","google-closure-compiler-js":"^20160916.0.0","istanbul":"^0.4.5","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","remap-istanbul":"^0.6.4","rollup":"^0.36.0","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.3.0","tslint":"^3.15.1","typescript":"^2.0.2","typings":"^1.4.0"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"839f5352bbcce9a7e05265fe9506b120329f1248","_id":"teambition-sdk@0.4.0","_shasum":"5fad51cd1845aec35400efd89def1bd14c3fb7b9","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.5.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"5fad51cd1845aec35400efd89def1bd14c3fb7b9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.4.0.tgz","integrity":"sha512-uAcdJy8mylAqmGASqrHS65d1gJjIn8w7M2VVxoxmGkEVyPTbZMyvjsYsa9Zdt2Q6Ic7OGLjscgkJiFC7ccT4QQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC+AQY7P+xN3EYxJErI0Uj43C1JgvyXIx3a0a6hkWkH1QIgX8N4amk9/5p+S9is5Crchq2BAltTx9P8AdW6uiVLqYk="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.4.0.tgz_1475143567591_0.20656005362980068"},"directories":{}},"0.4.1":{"name":"teambition-sdk","version":"0.4.1","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc tools/build/bundle.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts typings/globals/core-js/index.d.ts -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --sourcemap --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts typings/index.d.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.0","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","nyc":"^8.3.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.4.1","tslint":"^3.15.1","typescript":"^2.0.2","typings":"^1.4.0"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"c0e7f63b05f204591e5f8a6092c7038156457c35","_id":"teambition-sdk@0.4.1","_shasum":"55c18a91241314fe3a1f99eb2b9f78fffa728853","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.7.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"55c18a91241314fe3a1f99eb2b9f78fffa728853","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.4.1.tgz","integrity":"sha512-7EtA3ktjxugBawJkcpX3OypKgqeq2FQdLlGuNdfoRJG+AemJ+YiKHssA5dOS5Aoz3tObrXSIXCp6T/Z9I8n0Jw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBDXEGg+1UZ05Duod+tty36xKcF3CBKNBirhnyQeesiLAiAFmC88C2yKHffvwwD+Jpkh2mmpd+3FvL5rsDnkrxMbtA=="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.4.1.tgz_1476093672888_0.0798902097158134"},"directories":{}},"0.5.0":{"name":"teambition-sdk","version":"0.5.0","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc tools/build/bundle.d.ts src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc tools/build/bundle.d.ts src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts typings/globals/core-js/index.d.ts -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --sourcemap --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts typings/index.d.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts  tools/build/bundle.d.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","typings":"typings install","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.0","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","nyc":"^8.3.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.4.1","tslint":"^3.15.1","typescript":"^2.0.2","typings":"^1.4.0"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"3f8a09bea5e3af63967347946047c731c5022ba9","_id":"teambition-sdk@0.5.0","_shasum":"541add6dc2929c4a1eae08dd4394ea6ff3d49cf3","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.7.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"541add6dc2929c4a1eae08dd4394ea6ff3d49cf3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.5.0.tgz","integrity":"sha512-PoJdRn5DeGzd2POQf1N3rMTGrixeCEqOI61cMrEV8YrLzpq5C2RMuvrcSkyfUPHSiD3P6AM8Fmjoj2vYTS/QxQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCxNFNlenNcn38218Y8XyNdD97IQ1C7vab/MT/kchrGEAIgQy4+wnND7yRCiysDemo/a0rDiBRH32fBH3kUURDSskk="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.5.0.tgz_1476167945612_0.5505643885117024"},"directories":{}},"0.5.1":{"name":"teambition-sdk","version":"0.5.1","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --sourcemap --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp ./dist/mock-cjs/** ./.tmp/mock && cp ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.32","@types/node":"^6.0.45","@types/sinon":"^1.16.31","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.0","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","nyc":"^8.3.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.4.1","tslint":"^3.15.1","typescript":"^2.0.3"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"cb68dc17dda5c4e0d16d747d42d17768422e6099","_id":"teambition-sdk@0.5.1","_shasum":"054c4f2bfd5da99eb05325529471636cd9f344ee","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.7.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"054c4f2bfd5da99eb05325529471636cd9f344ee","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.5.1.tgz","integrity":"sha512-Ad0PC2MU7ZY1jmjiOPJDgaa4xJxrq2in8eU82OgLxW5Jtb9pTOVBu4+EC2uSuKFDpyGIkeDPSliqxhhMDcrgqQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDLIkuFsJ7ZgXk3bfCzLAbQQX5yxdieKjd7bL7+evQjIgIgGDx/3R7J3dDXbV9KPpqGWA18gedK4I6vOVuZgV9YXkg="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.5.1.tgz_1476186813694_0.588937611784786"},"directories":{}},"0.5.0-beta.1":{"name":"teambition-sdk","version":"0.5.0-beta.1","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --sourcemap --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.32","@types/node":"^6.0.45","@types/sinon":"^1.16.31","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.0","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","nyc":"^8.3.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.4.1","tslint":"^3.15.1","typescript":"^2.0.3"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"dc424d57d964713b1d2ec204c9508a91898846d0","_id":"teambition-sdk@0.5.0-beta.1","_shasum":"fef19c7a4bb4c33f49e6276566d886c8ec4dab60","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.8.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"fef19c7a4bb4c33f49e6276566d886c8ec4dab60","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.5.0-beta.1.tgz","integrity":"sha512-gwoeFewkGxOHByzz2Anj2xGNrGblSYPqYNH6fDD0NBB3dL9IjvFPPdwt2vt+XijkmG+tVzfXqtpPEoKBbXqWLQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD6DYeOvuk0wPZQyslWfozQ2MgfgGlEauUO2xtEic4DQwIhAIk+mOlNPzVzfEXkHQucHo646JwC9K7KS5Z9oUDa/fkk"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.5.0-beta.1.tgz_1476668336732_0.6848118037451059"},"directories":{}},"0.5.0-beta.3":{"name":"teambition-sdk","version":"0.5.0-beta.3","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.32","@types/node":"^6.0.45","@types/sinon":"^1.16.31","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.0","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","nyc":"^8.3.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.4.1","tslint":"^3.15.1","typescript":"^2.0.3"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"2dae3c42e2b09c9c90f4c38f13db70470a821075","_id":"teambition-sdk@0.5.0-beta.3","_shasum":"049e7cd973dff25c5756351b1cc869a79605d5a1","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.8.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"049e7cd973dff25c5756351b1cc869a79605d5a1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.5.0-beta.3.tgz","integrity":"sha512-XZQINffTpVmNgEwdMmQGYyNlkbNTRJMC//VwSqZwS8cXU3pKFKacAL+f2OgJiCRQY0YMUuM3YBDPFMEZE+vVAA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHSHbyb7BDvle+A+Bu7GsLPn9Tiz67s25uosCWaUwEMLAiAo6UWS9Xff0n/4LPEZ5gYjsu9wbA3bn9V/r6hZU+d9tg=="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.5.0-beta.3.tgz_1476691986156_0.6566916145384312"},"directories":{}},"0.5.2":{"name":"teambition-sdk","version":"0.5.2","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.32","@types/node":"^6.0.45","@types/sinon":"^1.16.31","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.0","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","nyc":"^8.3.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.4.1","tslint":"^3.15.1","typescript":"^2.0.3"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"db0566200d1ae20cad7c77e4d74ee0dbe0dabc25","_id":"teambition-sdk@0.5.2","_shasum":"f612d34912015c11d9f4e7cb59471512125f821c","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.8.1","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"f612d34912015c11d9f4e7cb59471512125f821c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.5.2.tgz","integrity":"sha512-Shy3UO1awvN5/MnDAt4iYLoau0df2r7Xo9FrvNsobaF0wYcWQFODct4Qv1a3v8KcXQwTntJtCPx1HYdLYQ2nxg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCWfziGWjrYzPUBxFTLzdu87holTLYXtWQg9xAOEQ0gdAIhANTRmDvuF2l72npTw8jbYdvcjpVif5a4T/2/kMIvS5L9"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.5.2.tgz_1476785528428_0.7985904477536678"},"directories":{}},"0.5.0-beta.4":{"name":"teambition-sdk","version":"0.5.0-beta.4","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.32","@types/node":"^6.0.45","@types/sinon":"^1.16.31","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.0","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","nyc":"^8.3.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.4.1","tslint":"^3.15.1","typescript":"^2.0.3"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"fb2fb1a33155748745abe7674b117251db3ed009","_id":"teambition-sdk@0.5.0-beta.4","_shasum":"aa1020364f14a82eeb4ba602d62a43050bd18cee","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"aa1020364f14a82eeb4ba602d62a43050bd18cee","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.5.0-beta.4.tgz","integrity":"sha512-IED3GOnlp+r5Y0hV5wHgJypBrJdRZy6Gscw7rQaVPACO/2dtvdwHF/4wDrtF2Wk8HexJmXc5mkyUmgn8FUnQjQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGXXLTJkMPKDm0IheCPzNBh88Oxn940+VZ8x1xEkK5NqAiEAvSTJP0c1apcM212imZrIhXr8BMuJFhVI0m6U3U2FVoM="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.5.0-beta.4.tgz_1476865342788_0.8674030944239348"},"directories":{}},"0.5.0-beta.5":{"name":"teambition-sdk","version":"0.5.0-beta.5","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.32","@types/node":"^6.0.45","@types/sinon":"^1.16.31","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.0","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","nyc":"^8.3.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.4.1","tslint":"^3.15.1","typescript":"^2.0.3"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"bf42b737300db7e4e3f67ff78b6abefbb02528ea","_id":"teambition-sdk@0.5.0-beta.5","_shasum":"f9e22ce98b37b2389f4855c866258c84f94d970b","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.7.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"f9e22ce98b37b2389f4855c866258c84f94d970b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.5.0-beta.5.tgz","integrity":"sha512-7vBWs38RuykrPAHyQ9Wn1rtGRaa5aTITX2tktepcxr2/7/AL7qh1b57jCTguPOtt48hCUkW3tg/5PJIcqFPRhQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCduEKst3O9o7tH/0dyQEEY9QW0Q1wENBkydqdh7LMSiQIhAJT8DDe/ZlwV0pRc/zyWqwB5eUlYu3/b3vZnEs3tSYRN"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.5.0-beta.5.tgz_1477280933195_0.09634202322922647"},"directories":{}},"0.6.0-rc.1":{"name":"teambition-sdk","version":"0.6.0-rc.1","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.32","@types/node":"^6.0.45","@types/sinon":"^1.16.31","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.2","nyc":"^8.3.2","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.6.0","tslint":"^3.15.1","typescript":"^2.0.6"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"b1c372d73fbbeb91710be17e6e899c1bee8fd6ec","_id":"teambition-sdk@0.6.0-rc.1","_shasum":"bd31e9a2bd1d17bccea42dcad0566977f4ff4b38","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"bd31e9a2bd1d17bccea42dcad0566977f4ff4b38","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.0-rc.1.tgz","integrity":"sha512-nPqRbcrTLnHBC2L2LAF1QxxRXgxOTgm0Qa6/WsmaCyrgSr32z1oVVCRXYHH2zHDJzozIn8pAzMhd5/L0azZT4g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCSi4kbiy2FkG3s0hiE0ObnkOrF0/tiiZvUO3FqcR+wgQIhAMI5WelmQ6+Y2TUXsqa+QUtUuYoeT5QRKBEK1UWQiwFO"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.6.0-rc.1.tgz_1477535769372_0.12010754575021565"},"directories":{}},"0.6.0-rc.2":{"name":"teambition-sdk","version":"0.6.0-rc.2","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.32","@types/node":"^6.0.45","@types/sinon":"^1.16.31","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.2","nyc":"^8.3.2","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.6.0","tslint":"^3.15.1","typescript":"^2.0.6"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"e25c49db81d1b315da826e6624ff16ca295af720","_id":"teambition-sdk@0.6.0-rc.2","_shasum":"9ffa8d3e333d22eaf95240c0c859195c96f8fa38","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"9ffa8d3e333d22eaf95240c0c859195c96f8fa38","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.0-rc.2.tgz","integrity":"sha512-qJls3z4gI0DArgVWf5rvU3kqvPQ/tUxJ109Xj8Fdy4Tzg0RKiIBf90VoLwp25T51WcCGPY1Q7LgGZPLa3+DZhA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHekn2cadHEwikPXcYM7WPdbdi5foxzCYYbk6bD0OskCAiEAhXh3JmY0amYzC0dGsneJPKh5Bohsv0AT5c+okb+Qe/I="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.6.0-rc.2.tgz_1477540744886_0.39170660939998925"},"directories":{}},"0.6.0":{"name":"teambition-sdk","version":"0.6.0","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.32","@types/node":"^6.0.45","@types/sinon":"^1.16.31","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.0","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.0","nyc":"^8.3.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.4","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.4.1","tslint":"^3.15.1","typescript":"^2.0.3"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"f4927e07d16879b23830339bc4cc3cb6843c5a26","_id":"teambition-sdk@0.6.0","_shasum":"b7955bf83e1e283b493d6fb0efe728743d15cb1a","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.9.1","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"b7955bf83e1e283b493d6fb0efe728743d15cb1a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.0.tgz","integrity":"sha512-m2krLNRjUvCEE9NXoLxvMKecPJJuDq4+BNy0eLDhbqOx6oCNHBI697UcP32+mD2hNYc4XRV3X8HaiZ1xUg+6Ug==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHDTRxQNWiKkKrWH7amiHj6c6vmBmB8YTyRRZvYE4hMpAiAC/lCCE4TPup1lpHGU03oEMshx20AQ36Vv2xHMAv/okg=="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.6.0.tgz_1477965961053_0.312831241870299"},"directories":{}},"0.5.3":{"name":"teambition-sdk","version":"0.5.3","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.32","@types/node":"^6.0.45","@types/sinon":"^1.16.31","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.2","nyc":"^8.3.2","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.6.0","tslint":"^3.15.1","typescript":"^2.0.6"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"0a2e711cbf85191cfaa69ecbb38e4da3803ae62c","_id":"teambition-sdk@0.5.3","_shasum":"f2f8bdbedafdfbcfc74fc52b43127591b889bc15","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.9.1","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"f2f8bdbedafdfbcfc74fc52b43127591b889bc15","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.5.3.tgz","integrity":"sha512-Kwe0Cm3IeHAyJjp1Hbpq25PgrJO7yNEk+OheR3WGcWCQRtvqxfmlCteJg6Am68a9oW4qiK2mCyhux9VuUY+3OQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAaESbLjtMAqf415X6MACgMONceLnKKSlubvVU8Wre9HAiAJhubhTgmE9LX59VJZ03mnfVfNCzaEPutSyn5d011DCQ=="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.5.3.tgz_1477967266723_0.6897689527831972"},"directories":{}},"0.6.1":{"name":"teambition-sdk","version":"0.6.1","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","dependencies":{"core-js":"^2.4.1","isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"5.0.0-beta.12","snapper-consumer":"^1.3.0","tslib":"^1.0.0","whatwg-fetch":"^1.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.32","@types/node":"^6.0.45","@types/sinon":"^1.16.31","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.2","nyc":"^8.3.2","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","sinon":"^1.17.2","sinon-chai":"^2.8.0","tman":"^1.6.0","ts-node":"^1.6.0","tslint":"^3.15.1","typescript":"^2.0.6"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"0e0705d73711e0638fc92481b5e376ad826fc441","_id":"teambition-sdk@0.6.1","_shasum":"c8ff671b4696f59ede44ead9886d5e7f80b75f45","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.9.1","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"c8ff671b4696f59ede44ead9886d5e7f80b75f45","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.1.tgz","integrity":"sha512-NUszqQqIinG4YbbFpuBMtAoSjleifxpNTgvxBY/o2iZzG1xns06hPV8Kr9ba4CGGK7K+3Jnx0VsIPCijfQ64cw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDkEp5lapk6mJQEQmdKKueJ63g+Ywobbt08LlzyBjlSNQIgOTxDPVhJ5c8D2Loz2SNGOhjn8wdBHy+YbrwK8Tmbeo0="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.6.1.tgz_1477967530144_0.663421212695539"},"directories":{}},"0.6.2":{"name":"teambition-sdk","version":"0.6.2","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.0-rc.2","snapper-consumer":"^1.3.0","tslib":"^1.0.0"},"dependencies":{"rrule":"github:teambition/rrule#v2.2.4","isomorphic-fetch":"^2.2.1","whatwg-fetch":"^1.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.32","@types/node":"^6.0.45","@types/sinon":"^1.16.31","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","core-js":"^2.4.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20160916.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.15.2","nyc":"^8.3.2","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.0.0-rc.2","sinon":"^1.17.2","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.0","tman":"^1.6.0","ts-node":"^1.6.0","tslib":"^1.0.0","tslint":"^3.15.1","typescript":"^2.0.6"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"ddfa8713c81838ddc3d006c4899842dd95180b7a","_id":"teambition-sdk@0.6.2","_shasum":"7f90678cf4a257e20c28749bac34fd852729c6f4","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.9.1","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"7f90678cf4a257e20c28749bac34fd852729c6f4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.2.tgz","integrity":"sha512-D5AZgWA3kr+e3DEQCVQ5ySlbjnSTdPMtU3qZhXdVB+lG7Dt9NCPllCuqg6IjR+WeK7IVhqMa1A1qRQqG9ERk4w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH8zCM1U0o5tirpZzqwpJoeM7p2SkRg81/e0l7Pjb6FTAiAMVLvXx0Y24aMOMi9RjfSDboh7r8bG0vLFRzdOZCRDaA=="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.6.2.tgz_1478508735097_0.26041126367636025"},"directories":{}},"0.6.3":{"name":"teambition-sdk","version":"0.6.3","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.0-rc.4","snapper-consumer":"^1.3.0","ts-helpers":"^1.1.2"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","whatwg-fetch":"^2.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.33","@types/node":"^6.0.45","@types/sinon":"^1.16.32","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","core-js":"^2.4.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20161024.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.16.0","nyc":"^9.0.1","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.0.0-rc.4","sinon":"^1.17.2","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.0","tman":"^1.6.0","ts-helpers":"^1.1.2","ts-node":"^1.7.0","tslint":"^3.15.1","typescript":"^2.1.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"31124db4801099cbc18399114eda4ca2cedd2817","_id":"teambition-sdk@0.6.3","_shasum":"3a1da170b980a35c597f2a505924f8a595de29f7","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.9.1","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"3a1da170b980a35c597f2a505924f8a595de29f7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.3.tgz","integrity":"sha512-FalRyxGNvbmyDMS3KRSjDqYRnNOoU37rUed8zsyj8AVtoFyk9OGISlo7+thzpBkMEsCIxI979qPXOvdors6hSw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEs9zL2/nE9YMadhbb1X3W9kqlBr30g3fizIrYQZq6VRAiEA9doIjTp2mMG3enWvK18mbbt4Fv3roPw8hfLuKvNaJyk="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.6.3.tgz_1479884095018_0.28623299882747233"},"directories":{}},"0.6.4":{"name":"teambition-sdk","version":"0.6.4","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test &&  nyc --reporter=html --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.0-rc.4","snapper-consumer":"^1.3.0","ts-helpers":"^1.1.2"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","whatwg-fetch":"^2.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.33","@types/node":"^6.0.45","@types/sinon":"^1.16.32","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","core-js":"^2.4.1","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20161024.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.16.0","nyc":"^10.0.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.0.0-rc.4","sinon":"^1.17.2","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.0","tman":"^1.6.0","ts-helpers":"^1.1.2","ts-node":"^1.7.0","tslint":"^4.0.2","typescript":"^2.1.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"fb3768f93dc09556b8911a881f19131a35373bae","_id":"teambition-sdk@0.6.4","_shasum":"da1164b32e487eb91b6c401d126423e1b3b07a60","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.9.1","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"da1164b32e487eb91b6c401d126423e1b3b07a60","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.4.tgz","integrity":"sha512-83DO/77nXi9NqPlX5pHdaoPywxcEeVgo2BmgsjpWRK83rAKRmgKWjE2EAbGTSzPvEM4LulX8mbsQb6u/ltyxpg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHvbo6eFGe1uKRABlABFQbijtz0oAVYK5/R8lHH3YdeKAiB7PYmjXYcR7eCRr6RJduGjzhPv815fnwbovMutEJLBCQ=="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.6.4.tgz_1480917225208_0.46839851583354175"},"directories":{}},"0.6.5":{"name":"teambition-sdk","version":"0.6.5","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.1","snapper-consumer":"^1.3.0","tslib":"^1.2.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","whatwg-fetch":"^2.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.33","@types/node":"^6.0.45","@types/sinon":"^1.16.32","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","core-js":"^2.4.1","coveralls":"^2.11.15","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20161024.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.16.0","nyc":"^10.0.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.0.1","sinon":"^1.17.2","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.0","tman":"^1.6.0","ts-node":"^1.7.0","tslib":"^1.2.0","tslint":"^4.1.1","typescript":"^2.1.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"7340c3483983e4e2623b443c805dfaf952e5dcae","_id":"teambition-sdk@0.6.5","_shasum":"58235d7500c056eee97cf29c11bcc2e950f34e14","_from":".","_npmVersion":"3.10.9","_nodeVersion":"6.9.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"58235d7500c056eee97cf29c11bcc2e950f34e14","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.5.tgz","integrity":"sha512-ojoMdTV0bDweolZVt1BVzreZJq/93dBPGNtIRH64nGQlgpP4GgQNHKq6UTd4qhqDxyFffkE8snwLoxP5UbE4dg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCkh2lgX6ywBk4BGXB3ZfZr2pyjxFeNqSQbiYr34WD39wIgGVPlNsWhQ9Dn47dihbBE/SZnDQrE/Do9rnIKKVPRiJU="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.6.5.tgz_1482309796112_0.7206115906592458"},"directories":{}},"0.6.6":{"name":"teambition-sdk","version":"0.6.6","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.1","snapper-consumer":"^1.3.0","tslib":"^1.2.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","whatwg-fetch":"^2.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.33","@types/node":"^6.0.45","@types/sinon":"^1.16.32","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","core-js":"^2.4.1","coveralls":"^2.11.15","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20161024.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.0.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.0.1","sinon":"^1.17.2","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.0","tman":"^1.6.0","ts-node":"^1.7.0","tslib":"^1.2.0","tslint":"^4.1.1","typescript":"^2.1.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"7d57cfd3f1cc027676404f3fc3f25bbd8f66f863","_id":"teambition-sdk@0.6.6","_shasum":"fd6cea91ab2b8fb9969e4110491c7f34c74b56ba","_from":".","_npmVersion":"3.10.9","_nodeVersion":"6.9.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"fd6cea91ab2b8fb9969e4110491c7f34c74b56ba","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.6.tgz","integrity":"sha512-IOgnwA3woDTuWEGB4bwylpirZK6bpsVNdcJXkRgiJTk3LUsvcVVI1oETwnGpqvob5AKJDBaIpwCDJn/Ep09YAg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBcEFJLBMGLCuOWvuHoJNRhZ1wbWzqi8hPxLetedMjgpAiEA46762PcVz6Nxfe6T9cuN/tD3u3eUHe/lElviO9EwUuA="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.6.6.tgz_1482730305516_0.8024191719014198"},"directories":{}},"0.7.0-alpha.1":{"name":"teambition-sdk","version":"0.7.0-alpha.1","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --importHelpers --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --importHelpers --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.1","snapper-consumer":"^1.3.0","tslib":"^1.2.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","whatwg-fetch":"^2.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/mocha":"^2.2.33","@types/node":"^6.0.45","@types/sinon":"^1.16.32","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","core-js":"^2.4.1","coveralls":"^2.11.15","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20161024.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.0.0","reactivedb":"^0.7.0-alpha.2","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.0.1","sinon":"^1.17.2","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.0","teambition-sdk-mock":"^0.6.6","tman":"^1.6.0","ts-node":"^1.7.0","tslib":"^1.5.0","tslint":"^4.1.1","typescript":"^2.1.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"8d83cea6eabb12d80985610f4b19536e046b6809","_id":"teambition-sdk@0.7.0-alpha.1","_shasum":"4f1c39208a36c16d49f4ad1fed1552b2f2d22390","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.9.4","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"4f1c39208a36c16d49f4ad1fed1552b2f2d22390","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.1.tgz","integrity":"sha512-SDjuvNJ+p4IQPLjxUGdkp88Pd7tB69xlIBGe3IdxYLUTKvMLVufQzBvDuj3/LSAXntKY5951rkaWWYUOZk7Hag==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGo+SqP8UZM0pg5L7YVUAkC3OaWDyept09v0Ja2CD27kAiEAxwIG13iP0ps+l+B8c1iHjaijeW/Y5p8smzIe4Rj2uHs="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.1.tgz_1484649228606_0.695128514431417"},"directories":{}},"0.7.0-alpha.2":{"name":"teambition-sdk","version":"0.7.0-alpha.2","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --importHelpers --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --importHelpers --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.1","snapper-consumer":"^1.3.0","tslib":"^1.2.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","whatwg-fetch":"^2.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/mocha":"^2.2.33","@types/node":"^6.0.45","@types/sinon":"^1.16.32","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","core-js":"^2.4.1","coveralls":"^2.11.15","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20161024.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.0.0","reactivedb":"^0.7.0-alpha.2","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.0.1","sinon":"^1.17.2","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.0","teambition-sdk-mock":"^0.6.6","tman":"^1.6.0","ts-node":"^1.7.0","tslib":"^1.5.0","tslint":"^4.1.1","typescript":"^2.1.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"52056d71bcf9e7a9dd86dee0dfd7ef87eb53029c","_id":"teambition-sdk@0.7.0-alpha.2","_shasum":"06d98f628a07e73df839f60f472c76e185e05b22","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.9.4","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"06d98f628a07e73df839f60f472c76e185e05b22","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.2.tgz","integrity":"sha512-9sdP3n/h+tFmd+7+v5qannKXDX7FU3flw36YjYFJ1AX0QLe7rj0lt/1TeaRHSU/RZqUygVdz1XSI87IvQWfl2A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDRtB76NnFit4sBaJ5fI0TK7SBZWJdieliQzjrto5SS2AiEAmulmSX/jfRqoRlfVRyw3pT+QMWSvc2bbofPHA2w8CVU="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.2.tgz_1484661466591_0.7238025404512882"},"directories":{}},"0.7.0-alpha.3":{"name":"teambition-sdk","version":"0.7.0-alpha.3","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --importHelpers --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --importHelpers --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.1","snapper-consumer":"^1.3.0","tslib":"^1.2.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","whatwg-fetch":"^2.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/mocha":"^2.2.33","@types/node":"^6.0.45","@types/sinon":"^1.16.32","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","core-js":"^2.4.1","coveralls":"^2.11.15","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20161024.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.0.0","reactivedb":"^0.7.0-alpha.2","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.0.1","sinon":"^1.17.2","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.0","teambition-sdk-mock":"^0.6.6","tman":"^1.6.0","ts-node":"^1.7.0","tslib":"^1.5.0","tslint":"^4.1.1","typescript":"^2.1.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"eb5f04673f905b04e5af1067cd57a183810f0f7c","_id":"teambition-sdk@0.7.0-alpha.3","_shasum":"a67329f9e312cfdded62f56619bac2f9374404b1","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.9.4","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"a67329f9e312cfdded62f56619bac2f9374404b1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.3.tgz","integrity":"sha512-T798mDGu6UN7ce5qXyo0NBB1Fk8gzIW9a0Ug/A168d70pyE1GF0WiKQEFXZYfCQCcEATFty/Gslx6uht0YbKhQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDbHHZWzrQwAkM/uDASXrF9x6UmSPGbDhvyFGcQ0zy9yAiATBuTGnUEaejsTJKIe6gF5BnTVLVF/Acj8cJdTJL0tjA=="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.3.tgz_1484709186891_0.5505525933112949"},"directories":{}},"0.6.7":{"name":"teambition-sdk","version":"0.6.7","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.1","snapper-consumer":"^1.3.0","tslib":"^1.2.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2","whatwg-fetch":"^2.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.33","@types/node":"^6.0.45","@types/sinon":"^1.16.32","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.32","chai":"^3.4.1","commitizen":"^2.8.6","core-js":"^2.4.1","coveralls":"^2.11.15","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^1.7.2","fetch-mock":"^5.5.0","google-closure-compiler-js":"^20161024.0.0","jsonrpc-lite":"^1.2.1","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.0.0","rollup":"^0.36.1","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^5.0.5","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.0.1","sinon":"^1.17.2","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.0","tman":"^1.6.0","ts-node":"^1.7.0","tslib":"^1.2.0","tslint":"^4.1.1","typescript":"^2.1.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"73ce1b7bfb397e706974fea197a378bc2e4e0696","_id":"teambition-sdk@0.6.7","_shasum":"d7782bea6c4a6b2c79f672b6108d7bae105b199c","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.9.4","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"d7782bea6c4a6b2c79f672b6108d7bae105b199c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.7.tgz","integrity":"sha512-TYLdTjZXQyKasEuj+aFl1ryvfy34gdWY27fnRXuvzHhYygTr1RUnY1fWRxLJFQV6Tarkp4Wktdnvq43gUyS7/g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCW2nCCpkdosNhMh4Qk+N1DJlAztWEApQdCK94qi14I6QIgS8Liyn8plFjaKNRVxXkeOoo8tMstJqPEkBNY0mDkgtw="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.6.7.tgz_1484712053036_0.5954760359600186"},"directories":{}},"0.6.8":{"name":"teambition-sdk","version":"0.6.8","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution  node && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck --isolatedModules -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_e2e && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.3","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2","whatwg-fetch":"^2.0.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/mocha":"^2.2.33","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.4.1","commitizen":"^2.9.5","core-js":"^2.4.1","coveralls":"^2.11.15","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.0.3","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","typescript":"^2.1.1"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"5dfa8f3854356a6053a5bc3defeba9756315b73c","_id":"teambition-sdk@0.6.8","_shasum":"f6f122e34ca190bd2fa3776a291f59a61450bd0c","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.9.4","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"f6f122e34ca190bd2fa3776a291f59a61450bd0c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.8.tgz","integrity":"sha512-q46a0VV664Zhtdlcy+Emscmcn5qTiERe6IPs5uaD7ALuDO7GGVZv0tzCYM+QpQmfBSx/0q9DvvjzdniWMoHqPw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCyGuRHFiWOjKsQr5jLbaq0QVDPHlTc4SI3tWqWknU3uQIhALf1xJlXkulUqnZLJ/KuqymZTwrGs3gW4mTQf9lW16gE"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.6.8.tgz_1485239979475_0.0820535400416702"},"directories":{}},"0.7.0-alpha.4":{"name":"teambition-sdk","version":"0.7.0-alpha.4","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","module":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015   --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp ./*(.) ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.11"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","commitizen":"^2.9.5","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"f6ef5dfdc5994874e9dfb0f01feed0316d9fcc1d","_id":"teambition-sdk@0.7.0-alpha.4","_shasum":"6257a202fd67c15dd12d01e97b50a67798193008","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"6257a202fd67c15dd12d01e97b50a67798193008","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.4.tgz","integrity":"sha512-coFa7MNVG8QpWkg/yn0ozdX45Zo4Gj9HKMP/DCbWPqVnf3ekg/sooDpiGeon2E5Z8YZeJGRSSS4IbXFjWJ5djw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDlrRGrS2oenXrmL2Mde+2eaKSLkDxmHSWTbIYgcCsbPQIhAMebIvL+JmoiOo3Z8C4O/6MUepqayf78+313Hajsp7CW"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.4.tgz_1487060872935_0.10569866420701146"},"directories":{}},"0.7.0-alpha.5":{"name":"teambition-sdk","version":"0.7.0-alpha.5","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","module":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015   --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.11"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","commitizen":"^2.9.5","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"_id":"teambition-sdk@0.7.0-alpha.5","_shasum":"cfaf84904a98148819b02d7549ee788572007bde","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"cfaf84904a98148819b02d7549ee788572007bde","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.5.tgz","integrity":"sha512-sHXTj6wRdQ0nDELPMiAi5xWlwWhAU4AQyeHFhg8zxVfOrZe1p9dIAgHueJC9x+83MqakCGc1gOxXZBkEyUv8Hg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICOw0MUq8VkMDGwiTunfWG5XfHeRqIsqH5UgAaR1WInAAiBOUf/0na/aV1EyLF99si1zsy8R2bvTi9Alf8YraoKmQg=="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.5.tgz_1487061242126_0.4372316524386406"},"directories":{}},"0.7.0-alpha.6":{"name":"teambition-sdk","version":"0.7.0-alpha.6","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015   --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["./**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.11"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","commitizen":"^2.9.5","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"_id":"teambition-sdk@0.7.0-alpha.6","_shasum":"7ab2d2787517b3827a665ee297ff2d0c4476262a","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"7ab2d2787517b3827a665ee297ff2d0c4476262a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.6.tgz","integrity":"sha512-saMuhf3Zlc5gOk9Z5Gz0BRYac1kQ+UtHquFx6IYwAZE2FQ5u8K+Cs2tIzPyh6eEAIwm0CO44BuzQontcDklEVg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCBAfc40bRHEenZcDggLMBUJj4mIjkXU2ec8Yv8tZpy3QIhANi6lDv+BZWhYAegWinv67VlA5hJzUdmm7NLed3RZZfk"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.6.tgz_1487061494061_0.5928734990302473"},"directories":{}},"0.7.0-alpha.7":{"name":"teambition-sdk","version":"0.7.0-alpha.7","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015   --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.11"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","commitizen":"^2.9.5","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"_id":"teambition-sdk@0.7.0-alpha.7","_shasum":"014a196c857db84682d88827d8d5a9c694752bb3","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"014a196c857db84682d88827d8d5a9c694752bb3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.7.tgz","integrity":"sha512-GmJWE6jCljzzMxFInA4tIB4wwRW08pZaYUr3LGWOVsBGUcDoA2dKRk75c3/dZ26kebqLiCXdXRqynVr74Kl4pA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCgcOIFwWKabxhUf8jx4iT9c9LwvImGDInB08hNgADkjAIhAKWDzGvkkUdm2txcgikVti1fgWfq13ZOOFdF2KDRY3uA"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.7.tgz_1487061617772_0.047671638894826174"},"directories":{}},"0.7.0-alpha.8":{"name":"teambition-sdk","version":"0.7.0-alpha.8","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015   --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.11"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","commitizen":"^2.9.5","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"_id":"teambition-sdk@0.7.0-alpha.8","_shasum":"84a7301c4f2cadaaebbd6f7ed68bd7b4db1e4f7a","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"84a7301c4f2cadaaebbd6f7ed68bd7b4db1e4f7a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.8.tgz","integrity":"sha512-xUuyqHU1stBmUvJ3C/6a8J0odzJcKYFPKONn+MRz1ECyVOmjRG/onii6dQqoeBy+0Spgx5KJoNrwbQPHtsFyGg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAJPn+R9ZUZG/2AehhE6+oCCPuFVJSz7UegK55WYo3xSAiEAwGhGuJKDjnEyCgiOdx4j4IcBUkkPbp0azuZiNZTp0lY="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.8.tgz_1487062019606_0.5461908462457359"},"directories":{}},"0.7.0-alpha.9":{"name":"teambition-sdk","version":"0.7.0-alpha.9","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.12"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"_id":"teambition-sdk@0.7.0-alpha.9","_shasum":"5e5d34a57130e7858f732a2c8832ab6437e27df8","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"5e5d34a57130e7858f732a2c8832ab6437e27df8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.9.tgz","integrity":"sha512-wVxtINNb5LwY2n6nUs77DLUBvWvc/DGqvNmXEyrM90L70Kpxx8wGaWOUou7t7hTJc1q5T9bLw7e0gux8Wjgozw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDBShQbwVUQdnb0NXhJDKdbY4izN+B8bNIvkNVQRLXoHQIgY/a0Temb9u1FDuNuJxQBBWQo7yHHElsNzHgs1+LZom8="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.9.tgz_1487236036422_0.008688054513186216"},"directories":{}},"0.7.0-alpha.10":{"name":"teambition-sdk","version":"0.7.0-alpha.10","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.12"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"_id":"teambition-sdk@0.7.0-alpha.10","_shasum":"e98eeab3abbddd0c8afa7d3e2c3bce64d3fe642e","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"e98eeab3abbddd0c8afa7d3e2c3bce64d3fe642e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.10.tgz","integrity":"sha512-HyIga84n44MbahL1ZsETV7PZnjDb+Zgl8Mf5o746IOvcRHAM4UN351yVoXqoubCyyN4GsY67oyrcg3rK/7uMTQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFNTO6uiC4X9g8EEbUo2Eaxt7cVV/jIQK/LvlqHoKkyJAiAUSFRJ961Ewoht/6AMmz9kfZAVvBxPOH/3rlYTXzNFIQ=="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.10.tgz_1487568171257_0.38154594018124044"},"directories":{}},"0.7.0-alpha.11":{"name":"teambition-sdk","version":"0.7.0-alpha.11","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.12"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"_id":"teambition-sdk@0.7.0-alpha.11","_shasum":"721722f3817bed306d210931f6f8ab8a8e9dae98","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"721722f3817bed306d210931f6f8ab8a8e9dae98","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.11.tgz","integrity":"sha512-9WegQy62cWOOD/1LIZ/DcU4PSwzNtiyArsCkvlsSPIQYkxyW0P2wKW55yxc3T8LzKAtBpC89bPwipQQoOAtoAA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDec3/JTkLMr8u+Q4+Vy/TjIiAtp9JyyyBLkMkL8YzWXQIhALPgN0fAWkON17MhZlHxTFng/h+aht7maMwdXFktaoGc"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.11.tgz_1487568437748_0.007900110445916653"},"directories":{}},"0.7.0-alpha.12":{"name":"teambition-sdk","version":"0.7.0-alpha.12","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.12"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"_id":"teambition-sdk@0.7.0-alpha.12","_shasum":"85e1529e5ee84b42f6cabbabc450f10a172c9e60","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"85e1529e5ee84b42f6cabbabc450f10a172c9e60","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.12.tgz","integrity":"sha512-oejR+MWzbGyPZBksSRdC5SriI8u+2J9QgSSDWRDAX9F2OBOXId/FytgIto4fvZSQoY2oGs+8BtnjR4+E3LCpzA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCb8B2C8wk8LuhQx6qv+ZWgxe25z2S4UyQyWmYUdqAgVgIgENWGmq0nxOMA2ojyED+bEP8wBgMCuvKBdnH3/MAk3Zc="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.12.tgz_1487568632691_0.057584859197959304"},"directories":{}},"0.7.0-alpha.13":{"name":"teambition-sdk","version":"0.7.0-alpha.13","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.12"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"_id":"teambition-sdk@0.7.0-alpha.13","_shasum":"79feb8c21cfb8c5b1185e5e5bba4e39446693304","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"79feb8c21cfb8c5b1185e5e5bba4e39446693304","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.13.tgz","integrity":"sha512-z8DyxJT7S/dCY5ecJi+mbN3vSMYZwkF6qpeipo2ZLslz92WI5UeWhWYFTCtiyl+iJ4X2GRghcI2fDPufAjkhug==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBEHUsu49Isr3PX/FPeUDSvw3KIC9sVpyJdCBpMz2+/6AiEApg6bjdoUIS7MCSEebL+3DPEgs/RmqtHmDiqLDAzpjlU="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.13.tgz_1487568737198_0.9100712747313082"},"directories":{}},"0.7.0-alpha.14":{"name":"teambition-sdk","version":"0.7.0-alpha.14","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.12"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"_id":"teambition-sdk@0.7.0-alpha.14","_shasum":"672b2d2a1d8c1deb049336e0d065970da2258c7d","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"672b2d2a1d8c1deb049336e0d065970da2258c7d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.14.tgz","integrity":"sha512-UtsiPoaEMcWUSWLUSoFCMq6WN9K7DgadZEY+PgnuX06tLxuXdU7DKeHz/5zX+aPdcDZhLQnENhHCk/JijepiMg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDDyV+Id6R4+R/Q14NOstQkF2h8JhQtFL8dDfj3mUR5wgIhAIwy+iRZnkJN4ZyPM3ZirbDS7MArYlfbdgHY4xKmGMq4"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.14.tgz_1487569009552_0.7848961285781115"},"directories":{}},"0.7.0-alpha.15":{"name":"teambition-sdk","version":"0.7.0-alpha.15","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.14"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"_id":"teambition-sdk@0.7.0-alpha.15","_shasum":"e48ef4520919bb2af8bb8740eb5d305c9935cd02","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"e48ef4520919bb2af8bb8740eb5d305c9935cd02","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.15.tgz","integrity":"sha512-C/gxK9Wz6k98ZBekqrXmo4m/xUAaiY4Fq1Mi9gNErRONYATudk4QIQsOnYzd7Uf3zuOt9uO9OOSBI9HtAbd7UQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEzzxVdqZNMgavLH8vex+lZgOFkIol3FV2gI5+dEMuSCAiEAt/5RSGyKKR/ry7xduk54DLuVxlqkMwEAL/XtK8Ujv+Y="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.15.tgz_1487669435606_0.41498470492661"},"directories":{}},"0.7.0-alpha.16":{"name":"teambition-sdk","version":"0.7.0-alpha.16","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.14"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"_id":"teambition-sdk@0.7.0-alpha.16","_shasum":"13ee163bec0737f946a90ba1a51e4d57631ad04d","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"13ee163bec0737f946a90ba1a51e4d57631ad04d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.16.tgz","integrity":"sha512-ALvy5HoFL7irHDTcjfeeW7qmQmorm1lrgHV1N52KKBdX/RfVcznFfLidFggMUBNbjoCbqALqrXWDOPPMUOazTQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBXN3CEnzEjAt61XiRinrLW4aFMmPbMApP/DQTbXk5K9AiAZSbXRrsuIae7oHrlc13suO8BVnjaLEGIvySzZhfTYiw=="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.16.tgz_1487732938362_0.43420977680943906"},"directories":{}},"0.7.0-alpha.17":{"name":"teambition-sdk","version":"0.7.0-alpha.17","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.1.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.14"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"_id":"teambition-sdk@0.7.0-alpha.17","_shasum":"546f94bb67299c2850324a55eea05d60f357f5d8","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"546f94bb67299c2850324a55eea05d60f357f5d8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.17.tgz","integrity":"sha512-d7p2EKI8UTil2Eg2ZszlDh/jWYwWmFjcEsPBhR6ftsSFIZ0szbRh1wNn7gP9R0+DxnnnDbFejbp3V3m7GevOsA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFdZrOPTpay4CyIyT9y2I2sb+y5+gQZdEMotfbI7ZG6LAiA2wB+LxLns5ifDDVlNFxfcTt9jj1Y0fDNXO8ofRDZ3Pg=="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.17.tgz_1487742418527_0.8288842162583023"},"directories":{}},"0.7.0-alpha.18":{"name":"teambition-sdk","version":"0.7.0-alpha.18","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.15"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"_id":"teambition-sdk@0.7.0-alpha.18","_shasum":"1542fdec620f7f139b6f62b751f03af9e7e90252","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"1542fdec620f7f139b6f62b751f03af9e7e90252","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.18.tgz","integrity":"sha512-VeoLfDfoiYP6fKssBuRMVCXOEywhX5ovAHMb67djhhaWxXwsqD+5N3ftjHJ4Y0n5atL+AxuPC9tAEh5HPdF4Pw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCdm7V0Ok/d0ziSj/NhVaBrEYHsu8pFajcdt0PrQyW1BwIhAOkto3eaYDavuwyS5UMxz/zW86C2dKsB+Kn+GLfkdNIl"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.18.tgz_1487747157541_0.30137840542010963"},"directories":{}},"0.7.0-alpha.19":{"name":"teambition-sdk","version":"0.7.0-alpha.19","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.15"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"_id":"teambition-sdk@0.7.0-alpha.19","_shasum":"56f1c6806acd0e13e54b7c7e9a6f9547ec20157c","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"56f1c6806acd0e13e54b7c7e9a6f9547ec20157c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.19.tgz","integrity":"sha512-ydEESjXH91R+DevdrB9WRA+cfnstN+b0k9e7+LEBWimdoQByyNxUf5fJgp5B9ecNSpoVk4kAvNrR7O+kS/Nb6Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC+/qceL3Tw7C/UU4pXg2gLG5MTjwl3a/7MGo/vL8WM7AIhAITblDTMWSLy8bC8s096ivVqwgKobm3Ijp99baGbyiaE"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.19.tgz_1487747863787_0.9344211756251752"},"directories":{}},"0.7.0-alpha.20":{"name":"teambition-sdk","version":"0.7.0-alpha.20","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.15"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.1.5"},"_id":"teambition-sdk@0.7.0-alpha.20","_shasum":"2169bcf565ca4083a7a26ec3f5352dc7238e2e01","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"2169bcf565ca4083a7a26ec3f5352dc7238e2e01","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.20.tgz","integrity":"sha512-LH0Ta4GzqR/P+qvHgTJwud7X5Ly3GlRKqteSZbwvvZRudt5cmxJ+UnJewpjO1+YKJlDm4g5P8OFDg1rXCiqteA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDdNYQPYPZZHV+0KQpPkkelvCCuw3QD5JG2Snzvt4eqQgIgdPcVRHTMsqVdecd+KGyjdQk9CobD4JTw6mVjoTrz8BY="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.20.tgz_1487815718219_0.0015196437016129494"},"directories":{}},"0.7.0-alpha.21":{"name":"teambition-sdk","version":"0.7.0-alpha.21","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.16"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.7.0-alpha.21","_shasum":"9857cce953aaa9d35dc55fcaef370e6c945418b1","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"9857cce953aaa9d35dc55fcaef370e6c945418b1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.21.tgz","integrity":"sha512-DsEn8eCrT3+mYxeO34zWsX1A8QGRjCdxkw8VLOl6/GNZkemMEsjynpj1Rm2gDKLg6AqPfTEO4fUBkWBmtXvoxQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD94DEgprlHRAYg5wY80dV29kPn8xvUssI/O/567ya32AIgKXFxsZ1y2fqsCWbfCvu61rjpF3BpduvYmks4mkocAn0="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.21.tgz_1487834795016_0.9805501368828118"},"directories":{}},"0.7.0-alpha.22":{"name":"teambition-sdk","version":"0.7.0-alpha.22","description":"Front-End SDK for Teambition","main":"./app.js","typings":"./app.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/app.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/app.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/app.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai,whatwg-fetch\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.16"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","@types/whatwg-fetch":"0.0.33","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.7.0-alpha.22","_shasum":"a4fda4a91cff45970f236cfd3665346a83771a6e","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"a4fda4a91cff45970f236cfd3665346a83771a6e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.22.tgz","integrity":"sha512-4D9ky8wtP1QVP4+82tyLbl74dRMcclOjhYrE5td4aJCdE9b26EIza7exKXgg+mL2/g4kHb+C9gtJBvesGHwHcA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJV67Ck1uBBPS0Q2/wCHHGXWbHGTMmDA1BcfF6AtzJFAIhAMBCrTJQKSm1zcaCpNB1bTF3pUwZaRvTUGyuSA25kJ/e"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.22.tgz_1487839302717_0.7759731695987284"},"directories":{}},"0.7.0-alpha.23":{"name":"teambition-sdk","version":"0.7.0-alpha.23","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/index.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/index.ts -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.0-alpha.16"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.7.0-alpha.23","_shasum":"acc1ebef5fd43f4dbf0f381d6bccf02c32dba334","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"acc1ebef5fd43f4dbf0f381d6bccf02c32dba334","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.0-alpha.23.tgz","integrity":"sha512-zHCFDPwsdW2jlKfnzNweuNa9NPeKBqPdkPxQR+7WPbIygpfEfcoWmsvBxJw25442DAw5+LyGkQf3gxqNIDeR7A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD0Gv3ZXp5p8GkC3aLwp5l2xwF/FPQWzEwikJsE1ej66QIgO1adszlNrAL1YDYsw0gqg831TEPYDMBC17vBRvHUq4g="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.0-alpha.23.tgz_1488352984030_0.7241913001053035"},"directories":{}},"0.7.1":{"name":"teambition-sdk","version":"0.7.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.1"},"devDependencies":{"@types/chai":"^3.4.34","@types/core-js":"^0.9.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.7.1","_shasum":"ae64b3442fe9b2b28f8de6384fc1f00cb94e0972","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"ae64b3442fe9b2b28f8de6384fc1f00cb94e0972","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.1.tgz","integrity":"sha512-T0RlnmIE2nPdweHdaPJz+Q87QekMszvEtSuxTdNv+LgU/SHwN33NGMhhj+AUzZAvukC2L3SC34fl9182xezamA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC7kDmHSjPEIJjWwPRklGqUJjxFd8y1qSDchBV9JaZJVwIhANXhB3LMSexnFhM4WkYIV5+LwF7MxaONNZ7dKGdI7L00"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.1.tgz_1488427292616_0.4454066138714552"},"directories":{}},"0.7.2":{"name":"teambition-sdk","version":"0.7.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.1"},"devDependencies":{"@types/chai":"^3.4.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.7.2","_shasum":"e1dace35ed9d44246b704b8d541e66c60bd9d617","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"e1dace35ed9d44246b704b8d541e66c60bd9d617","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.2.tgz","integrity":"sha512-eHDyyXQXVvjpIb0J0GgOT6fB73Z+JI7uMK8MajcohVs7WxMOREIUEsBEN7wMVGMX8eEYdgQsmtORqC5xy3ZVZQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFN0SwM9SXPzclJBM2yjvHxSbAyt+cyrm0amQLt2S+7PAiEAvFbaCSOmq7wKFbmXvllvgknRdYqnxqoqxMOi8uEwT/g="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.2.tgz_1488791833769_0.4191417957190424"},"directories":{}},"0.7.3":{"name":"teambition-sdk","version":"0.7.3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"reactivedb":"^0.7.2"},"devDependencies":{"@types/chai":"^3.4.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.5.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.7.3","_shasum":"981b2e3830c5b8fc72554a5584e505af164cf2c3","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"981b2e3830c5b8fc72554a5584e505af164cf2c3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.3.tgz","integrity":"sha512-vq+BVicR6Sw85HP0TJh9Kbe5DJNGYbfypejCMqkF2C4At5OSvCTBcfZSBXROUAeKPINRpA06rMAJ1T1539SsGQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDOOE47sMudnU+kc9fd64czys8QenFhcboaYf8BY9mOygIhALWwl6KdiVcK4F0RhiaaeXxnKYj1o3GBA1wdFBRQW6Oi"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.3.tgz_1490347659675_0.16105594532564282"},"directories":{}},"0.7.4":{"name":"teambition-sdk","version":"0.7.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"dependencies":{"reactivedb":"^0.7.2"},"devDependencies":{"@types/chai":"^3.4.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.6.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.7.4","_shasum":"73204cc4a8b3d14457365beda449eebb38e1409d","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"73204cc4a8b3d14457365beda449eebb38e1409d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.4.tgz","integrity":"sha512-xs9IIobn79oXPHmX4T8wWkr5wKOQ9aX7nStZvqOy4TLJExu7czop29raVHbJNG4VNhoPNoxPMOHYqfoQXEKMNg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEGHtCq50zEqQktKDLapOffN2E1tkRDHRKOufBaIQhwbAiEAsXbjzNGrXbPA8fJjqjb3bqiUh9j2IncMK8bm1OokrLg="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.4.tgz_1490847440026_0.2787723655346781"},"directories":{}},"0.7.5":{"name":"teambition-sdk","version":"0.7.5","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"dependencies":{"reactivedb":"^0.8.1"},"devDependencies":{"@types/chai":"^3.4.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.6.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.7.5","_shasum":"5479e44472be4a3de84e9bae65556347d98cda5c","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"5479e44472be4a3de84e9bae65556347d98cda5c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.5.tgz","integrity":"sha512-b0O1eFqrFM0dDi3BdyWla5c7CG8yqBM4gZ5FNJ8UqWFkIfzHt1jPyp50N1EfSvwrfgIJPKkTuYjHp8pnNMh/tg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBUHvnee/XnOw2IrxvkhzQl1Vzxf1hlTH6g7IZ8Yb0RcAiEAjT+or5pd8qiw/413bm/7F6oTBbMH5Cj9Vs5RCSthJYs="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.5.tgz_1490941747050_0.21366099501028657"},"directories":{}},"0.7.6":{"name":"teambition-sdk","version":"0.7.6","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"dependencies":{"reactivedb":"^0.8.1"},"devDependencies":{"@types/chai":"^3.4.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.6.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.7.6","_shasum":"ab1fec12ca78d87f55f1dda553fce86fa15cda27","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"ab1fec12ca78d87f55f1dda553fce86fa15cda27","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.6.tgz","integrity":"sha512-glnQMPyqTDJj1E6wBVGwhg1k9uzZl8mGZPGs8iKg9wC/3T9a9EbK+hMgHJn2/j/tVK/UIFQX6AzjHHDd2P1boA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDw9t08+aT2zPRsulzKI17aGcgTAP4/90jcfliI7nYIowIgJjbXUxN5xUlY23VM7IfrruBxd+WD6pew7QVcQxF2+eg="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.6.tgz_1491462499763_0.8663962997961789"},"directories":{}},"0.7.7":{"name":"teambition-sdk","version":"0.7.7","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"dependencies":{"reactivedb":"^0.8.1"},"devDependencies":{"@types/chai":"^3.4.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.6.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.7.7","_shasum":"c727fa82366ecdec432669071a450d5cc6499a88","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"c727fa82366ecdec432669071a450d5cc6499a88","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.7.tgz","integrity":"sha512-2ls13oyvpRafXJqJGR95TsbSaioOT41hPkn4e26+mhFRup//dI2tpYLZJL/vjIWQ2w474ShGoHiTeJYQbS8aNg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDm+3MO/utzm1s6jlUSmLwwv507F5MO2fk8zeGxFRtqqAIgPAHi4QEu/j5ChqSnDP7rr3vC0M6qke6RWEDDrzRFu1I="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.7.tgz_1491708712096_0.9371856935322285"},"directories":{}},"0.7.8":{"name":"teambition-sdk","version":"0.7.8","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"dependencies":{"reactivedb":"^0.8.1"},"devDependencies":{"@types/chai":"^3.4.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.6.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.7.8","_shasum":"e199fccda1daf3846dd797905dc974b7e7eb8eb9","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.2","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"e199fccda1daf3846dd797905dc974b7e7eb8eb9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.7.8.tgz","integrity":"sha512-DmFwerC1n+mSne3FdQ3OnlI4Fz9fV4LM3gPaezPIPI9401v+jS7Py6qgXSt3gneCTcf91xZaO23x0Jz5TESA0g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGH7OtSTuRhKGL4SkjIexDF0IxuGxXsJi+2qY3TjTkR+AiEA7/CEVNAfuVVbM7s8Ljsttz7OK9a6e+p055RMhzhHP9w="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.7.8.tgz_1491892449782_0.8649772692006081"},"directories":{}},"0.8.0":{"name":"teambition-sdk","version":"0.8.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"dependencies":{"reactivedb":"~0.9.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.6.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.8.0","_shasum":"a1daafdee5f7a4e33545fd0c37154c419b990e22","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"a1daafdee5f7a4e33545fd0c37154c419b990e22","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.0.tgz","integrity":"sha512-Rt8vM0O/OrgudxN5OB1V+kbB1CtIBvopUCmN+ROG5JcKxJGUlEYDmNNC6ZQrIKEpmtG5K1pU3/HbO2dKgNxwoA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCkKCSw1zXWoInZKJyJ6RViZUR6o5wnmWHPhgp3Eah/cgIhAOG67CTUr1dmbNHGMhpmxwLoPmfVvAGj0TkMe2FUxbn4"}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.8.0.tgz_1493022964700_0.08667873870581388"},"directories":{}},"0.8.1-alpha.0":{"name":"teambition-sdk","version":"0.8.1-alpha.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","reactivedb":"~0.9.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.6.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.8.1-alpha.0","_shasum":"d19d48e6b8a74ac395f1a261144c0308f049d453","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"d19d48e6b8a74ac395f1a261144c0308f049d453","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.1-alpha.0.tgz","integrity":"sha512-XVLRy3BsNCw59bcoA54pF6vKVUmX1P9rMtn7ja/qNS5oQ+TQ93h5TbwY0DpspJLXMUFN+pFiyKu7WcHLF6GXdA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEmRDI+WiHOrvXNEh948lij5PEmLEdeXE7Uh95hs4t+OAiEAlT1GU/L3ZbNyT1Q+/tUV5EHfn8TpNhe828oJbI35jVc="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.8.1-alpha.0.tgz_1493190873675_0.9466244021896273"},"directories":{}},"0.8.1":{"name":"teambition-sdk","version":"0.8.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --noImplicitReturns --experimentalDecorators --noImplicitAny --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"dependencies":{"reactivedb":"~0.9.0"},"devDependencies":{"@types/chai":"^3.4.34","@types/lovefield":"^2.0.32","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^2.0.0","tslib":"^1.6.0","tslint":"^4.3.1","tslint-eslint-rules":"^3.2.3","typescript":"^2.2.1"},"_id":"teambition-sdk@0.8.1","_shasum":"c8db0d27aab6af5e39dfabcf0d6ecc2508d99d67","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"c8db0d27aab6af5e39dfabcf0d6ecc2508d99d67","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.1.tgz","integrity":"sha512-FqBGfBMMC+bXLILmQOEmX/J4srPN/wnwxSA+yn9+M30aAUlJiLZFOdaYICtjNs2kZIcNALoxv7JHgt2ewWTPiA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAJAfaiysClRpy8T/ZL6dqWb1y2hDeg9mG3AZEsL0Hd/AiEAktoQHXsHr5CANQ5COIoYoTu9Sfc0Rm/muCFSgX6SEAo="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.8.1.tgz_1493269711268_0.4558586359489709"},"directories":{}},"0.8.2-alpha.0":{"name":"teambition-sdk","version":"0.8.2-alpha.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"dependencies":{"reactivedb":"~0.9.0"},"devDependencies":{"@types/chai":"^3.5.1","@types/lodash":"^4.14.63","@types/lovefield":"^2.0.32","@types/node":"^7.0.14","@types/sinon":"^2.1.3","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170423.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.2","nyc":"^10.2.0","rollup":"^0.41.6","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"github:teambition/rrule#v2.2.4","rxjs":"^5.3.0","sinon":"^2.1.0","sinon-chai":"^2.9.0","snapper-consumer":"^1.3.4","teambition-sdk-mock":"^0.6.8","tman":"^1.6.6","ts-node":"^3.0.2","tslib":"^1.6.1","tslint":"^5.1.0","tslint-eslint-rules":"^4.0.0","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.2-alpha.0","_shasum":"f32bca0cee60b816fe46e18c6d371652715d3e64","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"f32bca0cee60b816fe46e18c6d371652715d3e64","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.2-alpha.0.tgz","integrity":"sha512-AClSMnd34mFlWlqiHOD9zRqkNlHJoKG1O82CyJc/0rlvYcDApDvkSrxzBV5K/6YsVPlG0+wXqR5UnZn7OFXohA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC96/ldRvQL3pCyVmRMPB1dcgSEo/WEIGZqYXhe+XKiWwIgauwLtW4wEth9DJRetMyfOUFLut9cu8JKVOvyId7cavo="}]},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.8.2-alpha.0.tgz_1494209433436_0.2518752524629235"},"directories":{}},"0.8.2-alpha.1":{"name":"teambition-sdk","version":"0.8.2-alpha.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"2.2.0","rxjs":"^5.4.0","reactivedb":"~0.9.0","snapper-consumer":"^1.3.5","tslib":"^1.7.0"},"devDependencies":{"@types/chai":"^3.5.2","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170423.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^10.3.2","reactivedb":"0.9.5-alpha.0","rollup":"^0.41.6","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.5","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.0","tslint":"^5.2.0","tslint-eslint-rules":"^4.0.0","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.2-alpha.1","_shasum":"1abe4b7f03a1040dc64b590d8b9f3b62930469ab","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"1abe4b7f03a1040dc64b590d8b9f3b62930469ab","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.2-alpha.1.tgz","integrity":"sha512-7KUuV3h7mtEnLz6qx3blf9o5sAiUJ+2wpXK2Uvb21mYCRAHkTzp5HiYciT130yWtr3EO6FDCGo2UidtZsc0Lxw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGeVCkgIBMheF6wcPvgXKZAZyDOhAkeG9jDjrZFAEL4HAiAFEethNgxXR+SZ/oN9TP80yyIwOu3byi4bDfv5Mw+oTA=="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.8.2-alpha.1.tgz_1494839958771_0.8347559499088675"},"directories":{}},"0.8.2-alpha.2":{"name":"teambition-sdk","version":"0.8.2-alpha.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"2.2.0","rxjs":"^5.2.0","reactivedb":"*","snapper-consumer":"^1.3.5","tslib":"^1.6.1"},"devDependencies":{"@types/chai":"^3.5.2","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170423.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^10.3.2","reactivedb":"0.9.5-alpha.0","rollup":"^0.41.6","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.5","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.0","tslint":"^5.2.0","tslint-eslint-rules":"^4.0.0","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.2-alpha.2","_shasum":"690283ee61026778df6c9f44894d8d3ad2225cff","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"690283ee61026778df6c9f44894d8d3ad2225cff","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.2-alpha.2.tgz","integrity":"sha512-F6+I+duO5udr4Aht/ju8LsA/iIx7lXR4OsFzH2zxz9UQCb1mWq+HhoSQda+RjAllLXIbSMk3B4+xVq+ZvsfcEw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDf2q4ONsYkAJAU0FB0GxZZfc+no4MjXVnjTwKt691kOAiBGbId0WwGFxIbR8g0nAIxrV0ELk1ZefPcYgBRXI6fZgg=="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.8.2-alpha.2.tgz_1494840137418_0.47897909046150744"},"directories":{}},"0.8.2-alpha.3":{"name":"teambition-sdk","version":"0.8.2-alpha.3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"2.2.0","rxjs":"^5.2.0","reactivedb":"0.9.5-alpha.0","snapper-consumer":"^1.3.5","tslib":"^1.6.1"},"devDependencies":{"@types/chai":"^3.5.2","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170423.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^10.3.2","reactivedb":"0.9.5-alpha.0","rollup":"^0.41.6","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.5","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.0","tslint":"^5.2.0","tslint-eslint-rules":"^4.0.0","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.2-alpha.3","_shasum":"8124d208562919657d48b403ed2b0320ae1849b3","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"8124d208562919657d48b403ed2b0320ae1849b3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.2-alpha.3.tgz","integrity":"sha512-gGKDSCrHYu0uaxuaefnOitSE0zXtpHFVGC+a+KzNs72bvaxwr3Bpztum0gm0iMEBDpQby2nTXNL/uCWAVWA5bA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEG6x+Ksm3brJW6luufE1jqaxHZRV8HIvEi5weI27lnBAiAUNlYXZXB8k4ATM3pRNW87Mh5/4CoeLswOzxW40baggw=="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.8.2-alpha.3.tgz_1494841322702_0.09638804569840431"},"directories":{}},"0.8.2-alpha.4":{"name":"teambition-sdk","version":"0.8.2-alpha.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"rrule":"2.2.0","rxjs":"^5.2.0","reactivedb":"0.9.5-alpha.0","snapper-consumer":"^1.3.5","tslib":"^1.6.1"},"devDependencies":{"@types/chai":"^3.5.2","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170423.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^10.3.2","reactivedb":"0.9.5-alpha.0","rollup":"^0.41.6","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.5","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.0","tslint":"^5.2.0","tslint-eslint-rules":"^4.0.0","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.2-alpha.4","_shasum":"70debb80546a73efadaec9d843f638222bac909f","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"70debb80546a73efadaec9d843f638222bac909f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.2-alpha.4.tgz","integrity":"sha512-iNJH/0gLZL/BjY8jAdhUyVFurvky/nuNo6Q6F+dJE0/QLQhOQ3oAbtyCt0ClNEDXsiWOhWXtaXVa1s2a5UOlUg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDNSndnGPHQskoIz2ixETXSxOBZlg/gReIUVEZIk1GSjwIgN5OjjMj5UEm59HetAp0Los9/kVbkI76odbz9BLW/rCI="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.8.2-alpha.4.tgz_1495003771617_0.07470486359670758"},"directories":{}},"0.8.2-alpha.5":{"name":"teambition-sdk","version":"0.8.2-alpha.5","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.6","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^3.5.2","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170423.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^10.3.2","reactivedb":"~0.9.6","rollup":"^0.41.6","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.5","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.2.0","tslint-eslint-rules":"^4.0.0","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.2-alpha.5","_shasum":"597bb199397a645a7781b2b0cc8b1dea77522831","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"597bb199397a645a7781b2b0cc8b1dea77522831","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.2-alpha.5.tgz","integrity":"sha512-baS9TP8rZOOQL+WAycy5KGStgApidIV6mUGbxPeVi87yI0bJM09VlK/NfBrjrC2pqs/tB6shQd3Ak8YjlOp7Vg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHI/GAEdsTmGWlkmU9uOlkDX/V0mnvu3x8IetP5OFlOIAiBoCYTwZelOs5M7efFwg8t88fwWHrx00zPv49CbOMyQXQ=="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.8.2-alpha.5.tgz_1495174973731_0.46840903791598976"},"directories":{}},"0.8.2":{"name":"teambition-sdk","version":"0.8.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.6","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^3.5.2","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170423.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^10.3.2","reactivedb":"~0.9.6","rollup":"^0.41.6","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.5","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.2.0","tslint-eslint-rules":"^4.0.0","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.2","_shasum":"e3fdd9cebb8553a8e4cd39012beef7d22548c75c","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"e3fdd9cebb8553a8e4cd39012beef7d22548c75c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.2.tgz","integrity":"sha512-bMpOdyodAPulxVEzGBwIND3dRfQAKdYuYyeGhWcucMKET7inWpza/5rB/M4RRZ+G1m4gMPkRZGDV0cDMxoprFQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAZBDqZsiCBMEcmdJve+GQTp1xYXRt/sxKB0Pp60RH+CAiAKGKrO4kv7iQ3Q11vxh2jSYh8yipMh1LVRLsfCiBrzFQ=="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/teambition-sdk-0.8.2.tgz_1495175561007_0.8928476891014725"},"directories":{}},"0.8.3":{"name":"teambition-sdk","version":"0.8.3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.6","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^3.5.2","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170423.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^10.3.2","reactivedb":"~0.9.6","rollup":"^0.41.6","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.5","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.2.0","tslint-eslint-rules":"^4.0.0","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.3","_shasum":"3949816c77e0b12fa710429e528620b5e803395c","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"3949816c77e0b12fa710429e528620b5e803395c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.3.tgz","integrity":"sha512-9O0Av0wkc5RMySOQR3gKz1uFTqSOrbIA/D1fm0+adYfc6TSDj5Y3KkVCuP1IkZHZr3D39pXqncTsAgrvLWonqA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCYeX9ACCILkQKQBgrZUbeSlVllSRg8gD1InCpMco5uegIgHj/sMsiGexdmuwt25b81gS3+mEI2IFiLRfjsCsHBhNc="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.3.tgz_1495788479988_0.8748601889237761"},"directories":{}},"0.8.4-alpha.0":{"name":"teambition-sdk","version":"0.8.4-alpha.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.7","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^3.5.2","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170423.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^10.3.2","reactivedb":"~0.9.7","rollup":"^0.41.6","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.5","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.2.0","tslint-eslint-rules":"^4.0.0","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.4-alpha.0","_shasum":"3ec045f50f3552abfef735a0cc0844fcf0ff39ae","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"3ec045f50f3552abfef735a0cc0844fcf0ff39ae","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.4-alpha.0.tgz","integrity":"sha512-Z8T5gs/0xGq5lJdjS2qE2m7qRwX47EK3jetvh0Pwva7sU+jcg8hi0DlK4mK/0RR3Qrnfpo+uF3JpbCy2PHp8UQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHD9MWQ6H9ppmnFK+LFdvz7kvNYx2+qOCuJBsl3ahqdDAiEAu4UgYAO+e33NqElGHtQ+7pPUCyA8HEC0WSjQ/eELSbk="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.4-alpha.0.tgz_1495880405790_0.36592605896294117"},"directories":{}},"0.8.4":{"name":"teambition-sdk","version":"0.8.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.6","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^3.5.2","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^3.5.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170423.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^10.3.2","reactivedb":"~0.9.6","rollup":"^0.41.6","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.5","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.2.0","tslint-eslint-rules":"^4.0.0","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.4","_shasum":"e065dd2c995f3bc62e575ab4fdd4350a5bd44d2b","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"e065dd2c995f3bc62e575ab4fdd4350a5bd44d2b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.4.tgz","integrity":"sha512-Ri6BfGAudODVYhVekrn2/oc5e/stySfmQGi62KxOz+51Bl12pfsAApCra2RI9mnmK6oQgKyeMHnfH8sdn39Tuw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDRmjsNhY9xW1WG37/HMByrVJGKl5S3S2oLzna2ZGMY4AIhAJURzsArK307M6lGEAZ5k4Wo+nL78PEDVg7W3y3f9VeT"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.4.tgz_1496286944728_0.321011915570125"},"directories":{}},"0.6.9":{"name":"teambition-sdk","version":"0.6.9","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","commit":"npm run lint && git-cz","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --isolatedModules --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.3","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.4.1","commitizen":"^2.9.5","core-js":"^2.4.1","coveralls":"^2.11.15","cz-teambition-web-commit":"github:teambition/cz-teambition-web-commit","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.4.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^2.0.0","tslib":"^1.7.1","tslint":"^4.3.1","typescript":"^2.3.4","whatwg-fetch":"^2.0.0"},"config":{"commitizen":{"path":"node_modules/cz-teambition-web-commit"}},"gitHead":"199e47822f875f65b1c7f89c0a08fbe65c5a1c10","_id":"teambition-sdk@0.6.9","_shasum":"f670d51764a30e9d2dfd9ab2aa9127fa28d8a963","_from":".","_npmVersion":"4.2.0","_nodeVersion":"7.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"f670d51764a30e9d2dfd9ab2aa9127fa28d8a963","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.9.tgz","integrity":"sha512-EyQcdIJhMQklEmH7XbsI11y8AFl/eoqqpQZMyBF4nmdtw1W928ShrJum55GGz76xLfKAukz2jrcVjxKFYk8Tgw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCyaT/Z2DrtceiiNu9WBGOEJ1XdwUa9mftyzMOa7tWy9QIhAOafyzRbwz51E10bvkKH4pwbTADJb/BgBf+A0c2mnbfW"}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.6.9.tgz_1496747330245_0.33657012274488807"},"directories":{}},"0.8.5":{"name":"teambition-sdk","version":"0.8.5","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.5","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.2.0","tslint-eslint-rules":"^4.0.0","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.5","_shasum":"30a78f818d53b9af0488634c62c56caebae0713f","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.10.0","_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"dist":{"shasum":"30a78f818d53b9af0488634c62c56caebae0713f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.5.tgz","integrity":"sha512-tmtpgYkipVjyLOjehtklycLoq4e6cWoPO0LXJqwIBqHQ+LRbVMGdwAnI4R80D6BsCCh1KXV3KStNdK++krgKqw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGojdKXmqoxP6shw/isg7zhztsW0IsZW/fozY35LeF0nAiEA6KQgfVIX8QmHukGkszuf8w4hksVplJZWivRM+KTfeTg="}]},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.5.tgz_1496814892362_0.7902073434088379"},"directories":{}},"0.8.7":{"name":"teambition-sdk","version":"0.8.7","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.2","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.5","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.4.3","tslint-eslint-rules":"^4.1.1","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.7","_shasum":"137c8bbfa9c720c8edb24d896dc0597c996422a1","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"6.10.2","_npmUser":{"name":"miloas","email":"genesis.null@gmail.com"},"dist":{"shasum":"137c8bbfa9c720c8edb24d896dc0597c996422a1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.7.tgz","integrity":"sha512-XJBE4fGD5hLteVTuiZfTtZ6X23b8S87qWu75iChb0bIJ4CdWnQefMhLnOCqQYur+KDyQl952NkrTVARd3a2PHw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID6PakZAbcZXUgNJeFhNnytR1AnbINipLt/Ivjo7VeP4AiEAgxpFZB54u6ICOXx4oFGDvIbXB5KRuc3+KV1yEfRVsoE="}]},"maintainers":[{"name":"miloas","email":"genesis.null@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.7.tgz_1497605262222_0.9253810336813331"},"directories":{}},"0.8.8":{"name":"teambition-sdk","version":"0.8.8","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.4.3","tslint-eslint-rules":"^4.1.1","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.8","_shasum":"5c702db4d2c5749751ddf24eca2de7a3460b1bc2","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"5c702db4d2c5749751ddf24eca2de7a3460b1bc2","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.8.tgz","integrity":"sha512-tp4kvJVtyzfDB+nqTDFsNJEY60npIn0vWqt1csaEONjM3j6fxQywC7jYp0vST47I9HlbtLgAA0z4s+7eC9NQUg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFjNSUfpA1eNzQI6k/4FyXe4/JfgAdO3CDmbHHNDQ++7AiAq+hrZ6+0SqnnJ7idY9yfavAcYqSxX2Q755uWbOboDFw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.8.tgz_1498119816229_0.8332187314517796"},"directories":{}},"0.8.9":{"name":"teambition-sdk","version":"0.8.9","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.4.3","tslint-eslint-rules":"^4.1.1","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.9","_shasum":"f9e41f3d2476d2de2d6b0f18f156ece4810d0828","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"f9e41f3d2476d2de2d6b0f18f156ece4810d0828","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.9.tgz","integrity":"sha512-baAHL27GZczEldT21EN65UhCzN6nHsh5iQ54t262UNx8Ker7QKRowMoJatCMLi2mNIP4M0Yt+nx0SQ9rTXzJjA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGMPKDDzGBFz/3CUtdvVlQqrP0kcm4+oCRAbbCt4sJArAiEAhOn56OnokU/d9JxsF7LLWqTLlkL1qKJKEr0o3gAKuf4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.9.tgz_1498142998401_0.42258386430330575"},"directories":{}},"0.8.10":{"name":"teambition-sdk","version":"0.8.10","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^7.0.18","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.4.3","tslint-eslint-rules":"^4.1.1","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.10","_shasum":"e0dac6c67942ed048b43f90f245e20fa528cfdba","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"e0dac6c67942ed048b43f90f245e20fa528cfdba","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.10.tgz","integrity":"sha512-/a8oEg7sokSXugqiXvZaS/+iyAZOpCCVyi6aRx1HkKjiSpgoMYDWZYneuNuoZn1jeMe1/wlNpkVTgLxfwKS+CQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDSVi8OYswv+LGktc1kM/8aH3IiuQOY5L7ODX/Q/p22mAIhAODx1SP/Y1+oyH4zuh5ZYeKCnWXOokW4v7pZYB1hkH5O"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.10.tgz_1498557498820_0.8072801977396011"},"directories":{}},"0.6.10":{"name":"teambition-sdk","version":"0.6.10","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --isolatedModules --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.3","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2","isomorphic-fetch":"^2.2.1"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.4.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^2.0.0","tslib":"^1.7.1","tslint":"^4.3.1","typescript":"^2.3.4","whatwg-fetch":"^2.0.0"},"gitHead":"69176e6a2719d4d6b0f20b6706bfa09eda3ee0a3","_id":"teambition-sdk@0.6.10","_shasum":"d9823544e54b274179145efde0e8fd3d924d7bf4","_from":".","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"dist":{"shasum":"d9823544e54b274179145efde0e8fd3d924d7bf4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.10.tgz","integrity":"sha512-ZWAiwa99GBAkYuznnlo/wK1dcGK+pDf9+Uim4JJZwIOjpj3Ie4/3MN396R1ZT0VxkOL8N2YdtmfO6vmj4vIYfg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDDACVltwUsasznqJt6X14uqxSRWcTbWAUauNd6+PxNHAiBFcGzKd5xYVZFr7aUUCbDq6Mj24+D9ZfGGJL1dhc+1cQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.6.10.tgz_1498791753722_0.413071891060099"},"directories":{}},"0.8.11-alpha":{"name":"teambition-sdk","version":"0.8.11-alpha","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.10","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.4.3","tslint-eslint-rules":"^4.1.1","typescript":"^2.3.2"},"gitHead":"d70ddf619230d5087b7173d170d03c9a691b90fb","_id":"teambition-sdk@0.8.11-alpha","_shasum":"bc671f09c45701f7b0e744e093e6cb4a6674f8df","_from":".","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"dist":{"shasum":"bc671f09c45701f7b0e744e093e6cb4a6674f8df","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.11-alpha.tgz","integrity":"sha512-CjJWb0KuMteflmdcPbO5SqZ/Xbg5qlGLGJXjqFQkjTsMHfSl1D3SstoavSMmtktlfzi6N1bwXoMp1JkXJqJlvA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAaeOXNFFoRq+L75GA3wJMguczGqI1hzCrOb4FtCSFKVAiBIPFHuvVP/Ko35p9Tni7N9P3oEc8x6vSHFWckEyMCsJQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.11-alpha.tgz_1500027831242_0.8717698487453163"},"directories":{}},"0.8.11-alpha.1":{"name":"teambition-sdk","version":"0.8.11-alpha.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_all":"npm run build_all && npm run copy_files && npm publish ./dist/cjs && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.10","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.4.3","tslint-eslint-rules":"^4.1.1","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.11-alpha.1","_shasum":"9333b7b1d5af462075ebf6487900d4de063438c8","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"dist":{"shasum":"9333b7b1d5af462075ebf6487900d4de063438c8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.11-alpha.1.tgz","integrity":"sha512-0Z3Gg106QUKL3ZB8m1Ccl3UpEznBb/Q6QQzYKS3MeXwEeHVLtrcbEFAWrJij/1wBJRl7Qa4YIkdJoksYa9qT1w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/jMKLMVG5C86AiTEkVisYokuXkeoa3PMlVXwN4S2XLQIgd1K+q6Ux4XimWPcY0EWOh/ntXXPcBTmWv1B+nKkSMmY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.11-alpha.1.tgz_1500028398478_0.4009794252924621"},"directories":{}},"0.8.11-alpha.2":{"name":"teambition-sdk","version":"0.8.11-alpha.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.10","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.4.3","tslint-eslint-rules":"^4.1.1","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.11-alpha.2","_shasum":"9aeacb621132ce98853b1c8e4936078b0a498e9d","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"6.10.2","_npmUser":{"name":"miloas","email":"genesis.null@gmail.com"},"dist":{"shasum":"9aeacb621132ce98853b1c8e4936078b0a498e9d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.11-alpha.2.tgz","integrity":"sha512-ZzEPYtscFHl7GBiBIm2jMd4Yra7eNBnZp3yNVF2ePYzryqTcqXprVG/6zOkBpwUZAwK+BaSdG/HnVlK3Axs0Rw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD5haJGLP9XnfuXday9ks7T7PxnMKl4uPlSz70tF1an2AIhALWNo8AFuH/W5snAb38LDhIGz2PgDzQriY9yhEvVAnjL"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.11-alpha.2.tgz_1500279421553_0.03582997713238001"},"directories":{}},"0.8.11-alpha.3":{"name":"teambition-sdk","version":"0.8.11-alpha.3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.10","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.4.3","tslint-eslint-rules":"^4.1.1","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.11-alpha.3","_shasum":"74cd14b4c4d44babe8721a61ee073cca6c9da317","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"dist":{"shasum":"74cd14b4c4d44babe8721a61ee073cca6c9da317","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.11-alpha.3.tgz","integrity":"sha512-LrCEOsWlU5OG98/s038LYwMvj6ng8qvJO3QIQUQ+oq0bgXqMbtBC5PS6/X+Af2UT7safDl5iapNUONHATbE4Ew==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCUn28+iSRD94LwBuONScpC1jtsGGLlM4R7qWOI/7J3mQIgVx8YJII11oSE8Yz2Xy73FelS3dkCnTSgOphYKgwG2II="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.11-alpha.3.tgz_1500537263989_0.6138930036686361"},"directories":{}},"0.8.11-alpha.4":{"name":"teambition-sdk","version":"0.8.11-alpha.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.10","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.4.3","tslint-eslint-rules":"^4.1.1","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.11-alpha.4","_shasum":"814402b19def356ec949db176b9360cfffc64c83","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"dist":{"shasum":"814402b19def356ec949db176b9360cfffc64c83","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.11-alpha.4.tgz","integrity":"sha512-ixnb/pH3S+1VsXV4fBSFGtdJ/IQ7K/X9V0LmGNFHhwXR04v8o285TONuPL0rCurqzAPXdq1su669PZECXukJ2w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFs9MfcyiEUZotjNZ5ASBXKsvHp+BbslZPIyuywhLQLOAiEAvJKRgTDp4ge/sf3sWq0efWBxtnEXWBWbArd0eV71jyk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.11-alpha.4.tgz_1500950635992_0.35711665195412934"},"directories":{}},"0.8.11":{"name":"teambition-sdk","version":"0.8.11","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.10","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.4.3","tslint-eslint-rules":"^4.1.1","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.11","_shasum":"e74117ad8a2830182af6499db65e7f55e342e454","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"7.9.0","_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"dist":{"shasum":"e74117ad8a2830182af6499db65e7f55e342e454","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.11.tgz","integrity":"sha512-6A5wVb5S6O02j43YE2+xG3eXXhBUC0b4ANlneFervVaqzbOkeuP53yzvBCvgAdxhzWe36C8ITLtQ88Dzt0fxzg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCwkiv2jXO+xODLkvf3QbhCbMo+SAegQ32H2lr9mK9szwIhAPKr1IkquHvpYSWEZ6HW9twgxu619p3E1fMqVMnsqwb2"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.11.tgz_1501236688331_0.3928611862938851"},"directories":{}},"0.8.12":{"name":"teambition-sdk","version":"0.8.12","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.10","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.4.3","tslint-eslint-rules":"^4.1.1","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.12","_shasum":"7b9abd3b0162176773aadedd661da4412f3dc82e","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"6.10.2","_npmUser":{"name":"miloas","email":"genesis.null@gmail.com"},"dist":{"shasum":"7b9abd3b0162176773aadedd661da4412f3dc82e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.12.tgz","integrity":"sha512-mZN8ky6vUopouErDIEJClVpBEIzvcsFRNnK6qQsVCoN/Pandaa8tgKSTuAPJ+1vo9P5kAXlf5BvtQvU4zopd3A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBXzXV4HABBfI5F3G7UkTxQ9c2rubwaW7sJErwjrENjKAiEA+Z2vvo6G2Azwwr/PWsuf96tSdtuTUrp4gIG7pCBvcck="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.12.tgz_1501581742371_0.27840897953137755"},"directories":{}},"0.8.13":{"name":"teambition-sdk","version":"0.8.13","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.10","@types/sinon":"^2.2.1","@types/sinon-chai":"^2.7.27","chai":"^4.0.1","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.0","sinon":"^2.2.0","sinon-chai":"^2.10.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.6.7","ts-node":"^3.0.4","tslib":"^1.7.1","tslint":"^5.4.3","tslint-eslint-rules":"^4.1.1","typescript":"^2.3.2"},"_id":"teambition-sdk@0.8.13","_npmVersion":"5.3.0","_nodeVersion":"8.2.1","_npmUser":{"name":"miloas","email":"genesis.null@gmail.com"},"dist":{"integrity":"sha512-oHSy0Tfc4PMbWS7d1ngF/yQ6dwrjYZuNfzPpNUDOCBpp4LfK51MERtL62tPIKgqHXtjlCkQ5WgZ3+WGAs1EYFw==","shasum":"77f68b56ae40f186228d5d7eeea1bce89cb77293","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.13.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHDXx0HSExn777QNxpBI2ShArd9WVYdMFlZ3KhvbVVOXAiEA49XhPAO2HTD59BNQQHHoHd/+JNuQKRQEqPwc+Q7wVGQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.13.tgz_1501589727896_0.1629091603681445"},"directories":{}},"0.8.14":{"name":"teambition-sdk","version":"0.8.14","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.14","_shasum":"62812f933e491c14479220c7df0ebc613fd70672","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"4.2.0","_nodeVersion":"6.10.2","_npmUser":{"name":"miloas","email":"genesis.null@gmail.com"},"dist":{"shasum":"62812f933e491c14479220c7df0ebc613fd70672","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.14.tgz","integrity":"sha512-Q26LTrSl9vntQWNNG9mtLLwkO5JfR9e3ceu/xwt9tcRb5Mne7cOFBkVlBq1rwro9bnpSAjXpKOTD/LpiYd3oWA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDXMXo0QEwurdlyFjV6K0FqHvOvs5kW+qVjEFN+vOVD+gIhAPCK/v8wGZIN+qO/ksvicbXgNtSBc1T6gFaJfnHpbE9x"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.14.tgz_1501740032809_0.7137237407732755"},"directories":{}},"0.8.15":{"name":"teambition-sdk","version":"0.8.15","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.15","_shasum":"1f4d59e4c7f0868191534ced2b6097a04dc92c84","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"1f4d59e4c7f0868191534ced2b6097a04dc92c84","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.15.tgz","integrity":"sha512-8T7fykI4o06IPN6v5pG/+NnSFbaOpNpP2lRz5/M8qUOiYBQgpyqlHkHZwIxnWjBY2VemJhVeEzh3MYKXwMbW+w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICyFso2d+lv25UXLifmi+GBiffi6RroCLzFJdKHYwRXGAiEA/keZ4NGPCz9VFGFhNjuAo6IcCR1mSayYwpfT89gKqOg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.15.tgz_1502242715622_0.15394406323321164"},"directories":{}},"0.8.15-alpha.1-tapestry":{"name":"teambition-sdk","version":"0.8.15-alpha.1-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.15-alpha.1-tapestry","_shasum":"8c6e3ed550ab86e88010df408ed7cf7ee91715cc","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"8c6e3ed550ab86e88010df408ed7cf7ee91715cc","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.15-alpha.1-tapestry.tgz","integrity":"sha512-96eCc500Pmm2APWRCOUwu7BGqqnUERTeimgEn+dcH7lLJXSktKl3Z/WMrCo9Fjg26jD+jGxRPl1ckTaY9z5mrQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5bUmjmhjZ5tBBa/GmK53OwTHFQKeagoWksUOzfRddvQIhAKWuJ+ThtA2LtNVI6mx5pCHgN9xSVffY9+02BE9GUwbm"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.15-alpha.1-tapestry.tgz_1502351784693_0.5143531486392021"},"directories":{}},"0.8.16":{"name":"teambition-sdk","version":"0.8.16","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.16","_shasum":"36b7b03b7b7eb665df5f741bd58b849fbede46cf","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"36b7b03b7b7eb665df5f741bd58b849fbede46cf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.16.tgz","integrity":"sha512-S+TaIaJwzOQ+LFT8l+rJwTRFh5a/GDu+Ei1Fc+ATQYj8/29YYtBpXnJxHhBGitJG5xE8hBDHfS0M4k3rB320/A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEvrW0P87g1zIS/HNaBieCfZJFkMk3tH+7qh6jduhaTxAiEAi+BloDkDHCk2iazMdzgmEULn58/Ax2xuoOSJlhINruM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.16.tgz_1502357853604_0.9884721583221108"},"directories":{}},"0.8.17":{"name":"teambition-sdk","version":"0.8.17","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.9","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.17","_shasum":"9685bfaeaa9c955e7f54acfc3d86c7919e361b1a","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"9685bfaeaa9c955e7f54acfc3d86c7919e361b1a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.17.tgz","integrity":"sha512-7AtoLR+xtW7cz+fpkqa36TING8udiEk7CiMgQ6JV/gC7YkXA846uPt3rWm71UgA6mUM/+rL1hhqiKPx6Z7SlSA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDpjS/P4/1Nnw1ltyNe1zl9+jCDmYNH4en8XL2fGx7RAwIgRluJ1WGVyqlEs838ZiE34+E9Ten+F3ql9X6K/aJbfEI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.17.tgz_1502703665829_0.2903416177723557"},"directories":{}},"0.8.17-alpha.1":{"name":"teambition-sdk","version":"0.8.17-alpha.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.17-alpha.1","_shasum":"7490350dde2e4b2d1aa30f4cd9d6dd0222788aba","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"7490350dde2e4b2d1aa30f4cd9d6dd0222788aba","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.17-alpha.1.tgz","integrity":"sha512-rNNRih98o50oethc5ws6Nm/Im6AiiB9s2d2l6QnstrkoieRcVjb/E/RoaDPNhwoPqiwKOz1X52tR7qxZVlJgtQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD65KZ+mx1Pn8AwTAL0zfO3fNdftwxmdHzJlAKcBsxwvgIhAIFwFyvYfWcwp7uiWcXJfhJtbkHniLSb7HjSmiC1QOt+"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.17-alpha.1.tgz_1503450777330_0.4879813191946596"},"directories":{}},"0.8.17-alpha.2":{"name":"teambition-sdk","version":"0.8.17-alpha.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.17-alpha.2","_shasum":"6f4736b3c78e7eb6e46922683fd3ba417b8c27b7","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"6f4736b3c78e7eb6e46922683fd3ba417b8c27b7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.17-alpha.2.tgz","integrity":"sha512-u++c4tLAgILlpVyAmJVNO+gBBY0ab/QjYtJj5q5R1EquEM4ZTVFITKjnYO0UAoi4YvH425dWxlS56liSI4iXxg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDhnmAC+cAFCEeLVlbufiqCiIEvknbiUfuLj8wFIjBvVgIgS8G9tKb22oF3mloTacqUN5B/HBMjmixCRUoEJ1ukqfg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.17-alpha.2.tgz_1503902427546_0.6155374196823686"},"directories":{}},"0.8.18":{"name":"teambition-sdk","version":"0.8.18","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.18","_shasum":"062ee0d47256fe6e823bac5ab00e4a410281f3d3","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"062ee0d47256fe6e823bac5ab00e4a410281f3d3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.18.tgz","integrity":"sha512-4Mm9CsQAwXJc2oQUUzgjnIBuSS8izZiBdmbu4zkZBdtPl8PoqQZWNcd1444m7zlJgrFMPa+GabZsEtIwvTzzTw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEal3AsiBAyFhFGgQqO/gAnWZQnEgvq5LvRHtUhGzAWZAiBgA2DrUqepKh0krNt+HdXOIrDuKsJ8dzmSZB8GBsPdMw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.18.tgz_1503974383883_0.4979518863838166"},"directories":{}},"0.8.18-alpha.1-mobile-web":{"name":"teambition-sdk","version":"0.8.18-alpha.1-mobile-web","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.18-alpha.1-mobile-web","_shasum":"3d2485aa5fc9ffc9456c7cdc8da31f56742f7633","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"3d2485aa5fc9ffc9456c7cdc8da31f56742f7633","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.18-alpha.1-mobile-web.tgz","integrity":"sha512-vRIqM/Pb0UcFA8xajjiHWPNHwQKuqY9isUCxSOzLQrMSV7WeFg1E/7ogHrYtU6T+puqu1hL/LVHZOGpWwEb+Wg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDPD2NSbGqSZCNJcFdVQjdNH7n3zbcu5qMgt7GrGY3WKQIgOMwtomE8hFcctjrAcseEZdP+Pssm3sscfcTv1/4+wsI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.18-alpha.1-mobile-web.tgz_1504523118226_0.25479374290443957"},"directories":{}},"0.8.19-alpha.1-members-fix":{"name":"teambition-sdk","version":"0.8.19-alpha.1-members-fix","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.19-alpha.1-members-fix","_shasum":"6788afb412a137af86e3ebb225f91392d3eff762","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"6788afb412a137af86e3ebb225f91392d3eff762","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.19-alpha.1-members-fix.tgz","integrity":"sha512-vRIkVLTPa+5H62D7qd0tN3u/ozZnVg3UZdibFlWEahmY1zUiykd7mzelnOiZH5uBqvvP5dl6CMuCpu19iCOTMQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEJbZb2LEHK6NGhUQ4yO4GCW8ib1mSEGmIq06WKPkOdMAiEAifqz/6w3777an8VoehWbO9S2UD3s3h+r98PeK7JLPMo="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.19-alpha.1-members-fix.tgz_1504523440455_0.893212778493762"},"directories":{}},"0.8.19-alpha.2-members-fix":{"name":"teambition-sdk","version":"0.8.19-alpha.2-members-fix","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.19-alpha.2-members-fix","_shasum":"c923b64b4d36baecf2362162418e4d2b95a46aff","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"c923b64b4d36baecf2362162418e4d2b95a46aff","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.19-alpha.2-members-fix.tgz","integrity":"sha512-+M3FfKct+L/kfFpnBoY7wIOSUI4HR4TmtJGDxbg6BAh0cZ7y0OLHFqfmqoYW9gCu/C0u4F9k7DY4tVoXrLn2cg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDIJ/UiBochap9clZPANrECqqm2B/Z1eYPuX8DbmgrThAiEAn2jBm5iAtdPqfIy+SDmBsMlZa6phhSDZbCZg1C/SQAI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.19-alpha.2-members-fix.tgz_1504524337806_0.9389060465618968"},"directories":{}},"0.8.19":{"name":"teambition-sdk","version":"0.8.19","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.19","_shasum":"40e69545ec097f0b4dfe4f6a3335f9663182d28e","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"40e69545ec097f0b4dfe4f6a3335f9663182d28e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.19.tgz","integrity":"sha512-YR+OKPGYZsMB/ZHocqQmpDturGXE93zdSkr5Ki9ZKbufznx5NeZ1VHK9gGkD0G8tCcvhO5Gw/elJ31MAmXQw8Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCcg+YGPYceCbQuF8h2KMeluFmM22mchApkol6nWKXKywIhALRaz8PCEzSr/t8cA0C+/kxeQ1F3NSEPEQhrxD3SJ3ug"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.19.tgz_1504771667240_0.4831331770401448"},"directories":{}},"0.8.20-alpha.1-members-fix":{"name":"teambition-sdk","version":"0.8.20-alpha.1-members-fix","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.20-alpha.1-members-fix","_shasum":"03c25f7b9544432ff12cd857249ae6539407c629","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"03c25f7b9544432ff12cd857249ae6539407c629","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.20-alpha.1-members-fix.tgz","integrity":"sha512-Z0JywOikSW5AdidyGscJDqSSX51F5+c4e7AeVqF1Xya6vQqpPuc22aSMii6aU9vg4SKGeMCg7hzDE9eOSRBkgQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD0HSjlJOXOrMsZSyb3sfKtsGOqL3eJ3IlOuC+QIndwkwIgGBdOI572QlI6SNvnmquIemzqmK0rM1NXp+MMUN/yDGo="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.20-alpha.1-members-fix.tgz_1504772210424_0.8152971917297691"},"directories":{}},"0.8.20-alpha.2":{"name":"teambition-sdk","version":"0.8.20-alpha.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.1","@types/lodash":"^4.14.64","@types/lovefield":"^2.0.32","@types/node":"^8.0.14","@types/sinon":"^2.3.3","@types/sinon-chai":"^2.7.28","chai":"^4.1.0","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.10.0","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.2.3","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.4","nyc":"^11.0.1","reactivedb":"~0.9.9","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.0.2","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.2","sinon":"^2.3.8","sinon-chai":"^2.11.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.1","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.5.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.4.2"},"_id":"teambition-sdk@0.8.20-alpha.2","_shasum":"ece3e3564c52c4d96d9186f405cc381090599fe8","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"ece3e3564c52c4d96d9186f405cc381090599fe8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.20-alpha.2.tgz","integrity":"sha512-LT5vxQKcY3nHahy90w7358bL6dYPrumDYiseb1N0f+Gne+VpVeYQcDmhzanv/GgFLtkSE3HyxjPBgfLmMONvXw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC3G2eMC+KBANgZ/w12ZIG93pTtFnKsXw4SqhZT9LBzBgIhAJTA1Nehh8D5QSHSOsZLMmEWEg5AGaKKix7RWSf36D3h"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.20-alpha.2.tgz_1505316757741_0.22817647806368768"},"directories":{}},"0.8.20-alpha.3-join-user":{"name":"teambition-sdk","version":"0.8.20-alpha.3-join-user","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.4","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^2.3.8","sinon-chai":"^2.13.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.2"},"_id":"teambition-sdk@0.8.20-alpha.3-join-user","_shasum":"0c0df955b54b92509b561f263a0106698efdbbef","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"0c0df955b54b92509b561f263a0106698efdbbef","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.20-alpha.3-join-user.tgz","integrity":"sha512-c74eGxSBwp4h5ZfcerZsJ9xuC2AK/BtMyLlC9BMR1touY/NL15vsJKaIvZtmo7C/tqp7AeIlAMSPkPuw6R2KTQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHrHXqm+hOdCwtM9yxqQ43/EP2yV4jKzISQ8nMo3baSeAiEAiScrTjiyAzPTKviNRa3SzV14WyD+wZ5YT/r5wHtFn78="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.20-alpha.3-join-user.tgz_1505438998937_0.9054868039675057"},"directories":{}},"0.8.20":{"name":"teambition-sdk","version":"0.8.20","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.4","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^2.3.8","sinon-chai":"^2.13.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.2"},"_id":"teambition-sdk@0.8.20","_shasum":"d862ec31c19a0d1418cede557608975c17e9c68f","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"d862ec31c19a0d1418cede557608975c17e9c68f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.20.tgz","integrity":"sha512-cV8WCAsvj4rM8XtGAfE1rR9WSwjwqL4jYZGKFcugrbWvVNyl5S8eWlouAFku4DwDlnKbFpIl/sM/Kr+5G/RPzw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCn4Gck7KrBXYmSR0lreGHG1agSvwvJZRv/gLqLVlpUYQIgAMsw0wPLRYjj4weNXFYsqGlue+ewmgYz6A40g9DDx/M="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.20.tgz_1505470082472_0.406079315347597"},"directories":{}},"0.9.0-alpha.2":{"name":"teambition-sdk","version":"0.9.0-alpha.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_prerelease":"npm run build_all && npm run copy_files && npm publish ./dist/cjs --no-tag","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.4","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170521.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.42.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^2.3.8","sinon-chai":"^2.13.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.2"},"_id":"teambition-sdk@0.9.0-alpha.2","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"dist":{"integrity":"sha512-UsV6icnVQM/f7wVNMsUn8e1WJnWalpYzVxrXQtcrIsY8wD5zXjRRXpwzM0dmW2GZcs+fP9x9b8fVC4buoCvMog==","shasum":"0a860dc5041d1c5c0da4548bd61eb450d6d7af36","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.2.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCKEFVpnCG7EFgfr1YiPLUK90sjRCpN1spqA+zVAZIewgIhALM0IVTQYxoJwizCId+q6GE63IxH+znjVfX+KLz1NC4J"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.2.tgz_1506407019266_0.5428409941960126"},"directories":{}},"0.6.11":{"name":"teambition-sdk","version":"0.6.11","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --isolatedModules --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.3","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2","isomorphic-fetch":"^2.2.1"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.4.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^2.0.0","tslib":"^1.7.1","tslint":"^4.3.1","typescript":"^2.3.4","whatwg-fetch":"^2.0.0"},"gitHead":"97cc54f6306bb61f53f5d1cc5c8483b6b0f35151","_id":"teambition-sdk@0.6.11","_shasum":"5081642aa429e885c5f113b93c6da26eed22e1e4","_from":".","_npmVersion":"4.2.0","_nodeVersion":"7.10.1","_npmUser":{"name":"bjmin","email":"benjihuang818@gmail.com"},"dist":{"shasum":"5081642aa429e885c5f113b93c6da26eed22e1e4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.11.tgz","integrity":"sha512-nUClEdyjwU2caa6saVR6HH2+Mify1el2cA2ZLL1uiHaSqGF/nU5ghWr3rLCWGCz1Te8P9acgrutQeqq097/FGg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQChwZfG5hL7xB1UTrYiF2790vLWOBFUJxbostMjb5azJQIgObfGwoIEEsu7Si7+lYyklAFSXAmd0xkhQi9pfn8tns4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.6.11.tgz_1506509182257_0.710818317020312"},"directories":{}},"0.8.21":{"name":"teambition-sdk","version":"0.8.21","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.5","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.50.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.21","_shasum":"50899d4fb6a6ef9d8d4f899060504d8952d818a9","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"50899d4fb6a6ef9d8d4f899060504d8952d818a9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.21.tgz","integrity":"sha512-G6L05VMyiexeX2kYzCExD5QKSs7G3Z/g6q9C8zX7oNhr/1cPuW6BhDrdF1l2Dp3JWediP9RUsnvgBztSLHdqPg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC/cz+mDcnbfcQ2kgr5uNbtywVitXTsD3D5Di4WtiEv6QIgOyoPr41IeeBU7ah5jyWRLj+95VTd6WFUwgOehIBO0vY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.21.tgz_1506652476941_0.8347631958313286"},"directories":{}},"0.8.22":{"name":"teambition-sdk","version":"0.8.22","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.5","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.50.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.22","_shasum":"b4d8c7a3accfb46189db38efaddae4c50509c995","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"b4d8c7a3accfb46189db38efaddae4c50509c995","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.22.tgz","integrity":"sha512-YiXkGTJZ90bgeDpIsJE1OMrGETRY7vRwlRdexbEFj6+TX6fpoYUJmmLalOe5oSaMEjQFvS6hypGQcynQJnfYqg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDy+Qvgi3l72Rk1m73bEJFFMgoPYi0L9yVNmgC+8BM6AgIgIEmnYErxeg/RZFI6FQIjTTcDlSlXcmKkUVJ40EYZ79A="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.22.tgz_1507787374280_0.6909729416947812"},"directories":{}},"0.8.23-alpha.1-objectlinkschema":{"name":"teambition-sdk","version":"0.8.23-alpha.1-objectlinkschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.5","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.50.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.23-alpha.1-objectlinkschema","_shasum":"89eb849cb4a9dabf60e0676fc89180cc37d22ec6","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"89eb849cb4a9dabf60e0676fc89180cc37d22ec6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.23-alpha.1-objectlinkschema.tgz","integrity":"sha512-awWhZasqDb6iUCCIa7J45j8lMjaRGUF1NhAck6mqMsBIefVNC1tK0sQI77pgWaljOswouEnXJItCJogYxXUByg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA1KWjYrtQr5qhHGX/VvvaWgQn6HLf5zXnIfIH4woY8/AiEAqy5J6XZPyrF7kaW5jyBVE7Y9cEWOQj1ZgHy9AQGXy18="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.23-alpha.1-objectlinkschema.tgz_1507801871860_0.2542535599786788"},"directories":{}},"0.8.23-alpha.2-eventschema":{"name":"teambition-sdk","version":"0.8.23-alpha.2-eventschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.5","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.50.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.23-alpha.2-eventschema","_shasum":"fa3336499145f45dab88911fdade176c988dac55","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"fa3336499145f45dab88911fdade176c988dac55","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.23-alpha.2-eventschema.tgz","integrity":"sha512-IpvJ62FPGPdr87IetYZuAimHLgzbJafvsMDzs4lAiYvD2yBbYcyRVV/ueEUxeltnWUqlMn1jWJ6POg61ecmLIg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICNjqqGfKmOFwzGJa0v7Lf5ArJeAGAQX9/QMAkP8sNUCAiEAkvRhjqYYefYqL0IHHMnkQ4RW/bZbtjhjIQR0B9ZeAr4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.23-alpha.2-eventschema.tgz_1507875375942_0.599661196116358"},"directories":{}},"0.8.23":{"name":"teambition-sdk","version":"0.8.23","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.5","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.50.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.23","_shasum":"2d000169734ea9c1c3bfc1e25b5ab25ff42951f4","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"2d000169734ea9c1c3bfc1e25b5ab25ff42951f4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.23.tgz","integrity":"sha512-7Xto1IFX/+ZTy5wY+IHOiS8YRSZVzxMCrgedIb2lybbQu9YTmd7wLRFIeTRz+g2m/fitvfcnaFnHLwsB/iKbUQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5drXNlQ++smRT9ztjEC0OHdYYtmc+qzXGsi6r7tDlGQIhANnWXIkNscpx+0QlGpv7kqcIbjYgn7S6IZCnMP2Py5/3"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.23.tgz_1508485581942_0.03621135768480599"},"directories":{}},"0.8.22-patch.1-creatorisrobot":{"name":"teambition-sdk","version":"0.8.22-patch.1-creatorisrobot","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.5","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.50.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.22-patch.1-creatorisrobot","_shasum":"511be90843edfcd7644a56d38ff7f8dcf181cdc4","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"511be90843edfcd7644a56d38ff7f8dcf181cdc4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.22-patch.1-creatorisrobot.tgz","integrity":"sha512-Nw6iJqgv66rTm8puczQsLWiHQ2Lxf+L3nbpjnU8xaEbOOwoF1tRVmqzj5RgPFUuhoZSPaOYILhqZCD0Mln5JZA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEj9CRXmQtpbR2aiKtWbB+V3w8ExP9cxMlXlfnlG43UlAiBnRUHPggyarkJCd2D+9dNYKCmp9Skj+oi1E2Ti2NaDXw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.22-patch.1-creatorisrobot.tgz_1508922464669_0.8884889567270875"},"directories":{}},"0.8.24":{"name":"teambition-sdk","version":"0.8.24","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.5","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.50.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.24","_shasum":"2083fccb7509e774c5784dbad790622c9cefe31d","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"2083fccb7509e774c5784dbad790622c9cefe31d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.24.tgz","integrity":"sha512-B/0O1uvQ/hrBkz55NWnFXHSG1S/wMz/BMGLfNa+JvT6ptzF+nPV2BmbIIuUtLKlLxdUUclQOzfm8cPxY615Vgw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBvirU5kFugYyANILBOhHxA9pBBrdxbG4I60G9DqpSTuAiBEcqFCHsyO1WsIjidu70+OrUIeaJNVJYasVvWxu7JDrA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.24.tgz_1508990460813_0.23238530848175287"},"directories":{}},"0.8.25-alpha.1-objectlinkshcema":{"name":"teambition-sdk","version":"0.8.25-alpha.1-objectlinkshcema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.5","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.50.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.25-alpha.1-objectlinkshcema","_shasum":"586c1762e5521c554b23823eeb548d670dcfa5aa","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"586c1762e5521c554b23823eeb548d670dcfa5aa","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.25-alpha.1-objectlinkshcema.tgz","integrity":"sha512-GClpZ8IgVEZZqSpYwBMgbxrwHtRYrfEiyJTHHgM/WQCkqmv1wy5cYflM9GZD/MxHFZ3kfBjzOQC5GAEip3anfA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH49P6gmqgM3Z7OwIy2M84KkY/n9tp4o5CByLQxP71HZAiEA07qYGhTu8iWINGcyJJ8HXcinqOSqa8Yntm+Tg9fHBus="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.25-alpha.1-objectlinkshcema.tgz_1509092202100_0.3975931142922491"},"directories":{}},"0.8.25":{"name":"teambition-sdk","version":"0.8.25","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.5","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.50.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.25","_shasum":"13b083829cb0ced1c60e6ee7a240eebdc77c0d46","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"13b083829cb0ced1c60e6ee7a240eebdc77c0d46","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.25.tgz","integrity":"sha512-8pYxWKQdzM0JenhjXjL27MoEhWXOHIEoGn5Al/w5VaSUEXYpPH4hPym7tp+FRzcgQOHMq9FigUaUjjC8VXC3Bw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD4fTAZUkwD+m6oXuT/5pNN/rqvi2sZg1ZAaMzit6gZ7gIgWfCvA4QhtuXcwBxscxQFvuSdqRjzg4pjRGPL1EhNQdg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.25.tgz_1509615891726_0.06922236434184015"},"directories":{}},"0.8.26-alpha.1-members-fix":{"name":"teambition-sdk","version":"0.8.26-alpha.1-members-fix","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.5","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.50.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.26-alpha.1-members-fix","_shasum":"f2f1a67020ccf3a954f0fe0d4388e0f6f05a8cb2","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"f2f1a67020ccf3a954f0fe0d4388e0f6f05a8cb2","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26-alpha.1-members-fix.tgz","integrity":"sha512-HjwfcfNW+DIsYsKemeoE3yOXz8zlYMHn+59yIAW2o1lqgd00R8V5gonTsUvTV+f091IpNKuX3RkovojZHz2mDg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCmflzODAtk5okYIkjB4k/9H7AogQFuxic+xBUguMGLKwIgeFDLCbOJj2WQfSzWtqoW7pOJ716Vr+ZBETFK80EauQM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26-alpha.1-members-fix.tgz_1510027486672_0.13407029979862273"},"directories":{}},"0.8.26-alpha.1-sprintschema":{"name":"teambition-sdk","version":"0.8.26-alpha.1-sprintschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.5","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.50.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.26-alpha.1-sprintschema","_shasum":"b8f7ce615860a02666db687f70abed07021f454b","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"b8f7ce615860a02666db687f70abed07021f454b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26-alpha.1-sprintschema.tgz","integrity":"sha512-AzROPiQ1vNMJFNRnTJWSPJg+AHwUyt26rjgz+tePBxgCCjkaI4M08i4joh/A7j4JvHRSu2YE5MeNzOrH8yP3RQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQClolgCpRnOnAGDgav2+RyXG7qkbFDIigNRJxZMxE7S2AIgMhlk6ik+ooTCEnUO5H7Bfu4BhYpWEOrrFnd+c1/PSG8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26-alpha.1-sprintschema.tgz_1510913232335_0.9825213749427348"},"directories":{}},"0.8.26-alpha.2-sprintschema":{"name":"teambition-sdk","version":"0.8.26-alpha.2-sprintschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^2.3.5","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^2.13.1","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.50.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.26-alpha.2-sprintschema","_shasum":"7d5accacb78078ccefaaf04ab78d65d055d07855","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"7d5accacb78078ccefaaf04ab78d65d055d07855","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26-alpha.2-sprintschema.tgz","integrity":"sha512-dRr+ZDSK9Rz7h7UEbDcyz8JuNMqlaIb5rLJKK1EOvdWUR+042zHq8UAXknEPSXHQMyaXoHmwrKZHdoD3pKDbfQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGj3XPN7jBaYzH5umjggv62oQcUGXYIGedRMXjKkTCfBAiEAuz4XEs8Z6E50EDl7o2V1cNuoLdSrJ20hGfTZ+LWZf2E="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26-alpha.2-sprintschema.tgz_1510913384839_0.896080968901515"},"directories":{}},"0.8.26-alpha.3-smartgroupschema":{"name":"teambition-sdk","version":"0.8.26-alpha.3-smartgroupschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.26-alpha.3-smartgroupschema","_shasum":"8a805c097cf3709ae1d08dc1ba1d2ee38b680c80","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"8a805c097cf3709ae1d08dc1ba1d2ee38b680c80","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26-alpha.3-smartgroupschema.tgz","integrity":"sha512-rjwIMz+9y4hm49/y51e4E2wyBQGSMA/Uep2JIW5XfQ2DytGMgdOmdYbmae5li+wuiO+7uYA8KP67y5tMRJErsA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHHwd9676pfqMcPv5QTe3IYAXbveo/h1pOJHsQ9vf/mjAiAQ+ONhSmIPI637TqxCQTUDdl2Hxl9JrOa2gHMNsFgzcA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26-alpha.3-smartgroupschema.tgz_1510976289524_0.7724449406377971"},"directories":{}},"0.8.26-alpha.4-taskschemasprint":{"name":"teambition-sdk","version":"0.8.26-alpha.4-taskschemasprint","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.26-alpha.4-taskschemasprint","_shasum":"7e58aba0bedf5b155837cae1db972dfde780ae92","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"7e58aba0bedf5b155837cae1db972dfde780ae92","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26-alpha.4-taskschemasprint.tgz","integrity":"sha512-ASdP3W//+zfGARHRsUjdU+PCTlZxXz8ed47mXpRMJcvydqt5/PZmBhsOlqkY18TZ0PvVOuLPANqhC7XFIxF13Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDyRlM9gQTf0rESf6K7cbeerc5LYub1pXfAAXqYLYxAxAIhAIVgoVXHs2TUP012GLzhse7peMKxEVJQ5bYzsgWRu21n"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26-alpha.4-taskschemasprint.tgz_1511257919855_0.4221911570057273"},"directories":{}},"0.8.26-alpha.5-taskschemasprint":{"name":"teambition-sdk","version":"0.8.26-alpha.5-taskschemasprint","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.26-alpha.5-taskschemasprint","_shasum":"bcd2b84531960f37f11395c78e04b042fbe817c9","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"bcd2b84531960f37f11395c78e04b042fbe817c9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26-alpha.5-taskschemasprint.tgz","integrity":"sha512-R98RrGVpsgVCXG4M4UXnKsptDzudsNmRMcylQZkrD/+DZgjwOLPAzzw5SlETGQeBlnj4nz5Cg0+a6IoCslmObg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAGfTxedlC6M/Ulr7+6xRCXeaqkyItDLwPF7qZvAtj/vAiEAlMxmGJMTWQRRXvuPZBxdxca+SakIoVMdWcnMnuTt990="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26-alpha.5-taskschemasprint.tgz_1511259115702_0.17403496010228992"},"directories":{}},"0.8.26-alpha.6-customlinkfieldsocket":{"name":"teambition-sdk","version":"0.8.26-alpha.6-customlinkfieldsocket","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.26-alpha.6-customlinkfieldsocket","_shasum":"35decc913d0a43d9b777d5f3b06eac675a257c28","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"35decc913d0a43d9b777d5f3b06eac675a257c28","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26-alpha.6-customlinkfieldsocket.tgz","integrity":"sha512-uPOgJhucKlXS9zOK/5P7ZzHD3a8nCtlbDlZDDH/frqAPhZiP1sZwXGD4n/kKzJROHBa3ikdu72RMTON5wH1IgQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDZ3Zu7fM9ki9zHRSz5kxCGL4x0d46Now6H4i5TSwOaZwIgK2Lomaz3/I7gqme5Yctm51xUcnqxGnUN9bJ1CwPS9iI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26-alpha.6-customlinkfieldsocket.tgz_1511427415934_0.6906306087039411"},"directories":{}},"0.8.26-alpha.7-wschanges":{"name":"teambition-sdk","version":"0.8.26-alpha.7-wschanges","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.26-alpha.7-wschanges","_shasum":"fb6aaffcb12819d2efaf866d25c86d300eba9379","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"fb6aaffcb12819d2efaf866d25c86d300eba9379","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26-alpha.7-wschanges.tgz","integrity":"sha512-CIGDMRoPuOv/vN7qjo7kNrXQnF/ZXFUZ6kxS69r2JtDeZscDXZPPoLmyKkQRo3fniPV7b+80h5osMuyQDv951Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCFqaxLXxdsJR+wGLn5wJvgOeKD7qEUJKWSfv88aIb5PQIhAM7J3i/aj6RAnf/V2V2PxasgfNJQxezlmn4PRSFGtUjU"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26-alpha.7-wschanges.tgz_1511526138536_0.9464100699406117"},"directories":{}},"0.9.0-alpha.1-allday":{"name":"teambition-sdk","version":"0.9.0-alpha.1-allday","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.9.0-alpha.1-allday","_shasum":"3710c0e22bbd3e3f0e2d8b92fc86fe896006d2a0","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"3710c0e22bbd3e3f0e2d8b92fc86fe896006d2a0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.1-allday.tgz","integrity":"sha512-BgHyeLcWz1Hs9XsxbdqhvSRKRCHfv7T+hhYp5u21FNw2DylI+DQiWPMREipcyiHARFetJMlJ0Lj8OpZrc/OmDQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD8kRbRWLl2nuU75htxy9IpskqZCp+azUHDpH2X/twD0AIhAOzF3xpV4smS4sr2oH7MFw1r8I9ySAvmv7cTWXwBgJZq"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.1-allday.tgz_1511954370198_0.4016685853712261"},"directories":{}},"0.9.0-alpha.2-allday":{"name":"teambition-sdk","version":"0.9.0-alpha.2-allday","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.9.0-alpha.2-allday","_shasum":"71c8c363c395a4904f52874ef015ac112cb65a8f","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"71c8c363c395a4904f52874ef015ac112cb65a8f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.2-allday.tgz","integrity":"sha512-UxOsy0WsTi0qHAAeom8t71ZbVbtnRmU03JkLUCGpmD/CDs51DbeYMAHvvI2zBETfJ1TELgg6ibfCoMWtXqS82A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEMFhbOE00hWUVqJ3YsfY0WboL1B3qBlJvrlv699qO28AiEA1lHPb6n3YvwlVVuzskVg9lBwJWNx1j3+olsE+2SxjFY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.2-allday.tgz_1511961192631_0.43331723962910473"},"directories":{}},"0.8.26-alpha.8-wsremoves":{"name":"teambition-sdk","version":"0.8.26-alpha.8-wsremoves","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.26-alpha.8-wsremoves","_shasum":"fca4425a89f78f0eb25e9129808b5e3f3483badc","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"fca4425a89f78f0eb25e9129808b5e3f3483badc","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26-alpha.8-wsremoves.tgz","integrity":"sha512-i3f0p2TcChWGMseVT8hZd95HNjaSH8v7dePv9A5kKPWyeDDAg1pfKd6flqPmzGTLoj2SSx7GkwG5Nnvmj9CMNg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCI4HLzLkqWE8c33gx+ilrOBN9+Ss1BGKHNh+TTcDwPAgIgM6xIzxtn71hMCV0prR5hKHKEYZqRNkUd6+aFLH+MVGU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26-alpha.8-wsremoves.tgz_1511965473963_0.041596391471102834"},"directories":{}},"0.8.26-alpha.9-sprintschema":{"name":"teambition-sdk","version":"0.8.26-alpha.9-sprintschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.26-alpha.9-sprintschema","_shasum":"265de41df156ec710732e6df66550f8cca96a204","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"265de41df156ec710732e6df66550f8cca96a204","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26-alpha.9-sprintschema.tgz","integrity":"sha512-vkTNt7GvsKzVZb8qzivUALvnGaaEw8t2oe9DPdJuSZ6sMw9hFhD+/oxDq8JFEHysYv5u2NXTxNw2onyiCWZitg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC2cNks1/n+QKusz/uTP3dNDwKWOREOKFE6usn5lbNKGwIhAK6UMDAN3nl+fY5pEly0gG05bFsK18sjJCzIJaES47yU"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26-alpha.9-sprintschema.tgz_1512014873610_0.24138228502124548"},"directories":{}},"0.8.26-alpha.10-sprintschema":{"name":"teambition-sdk","version":"0.8.26-alpha.10-sprintschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.26-alpha.10-sprintschema","_shasum":"ae228720efc3625d63b8bba2f00321748c26fc28","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"ae228720efc3625d63b8bba2f00321748c26fc28","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26-alpha.10-sprintschema.tgz","integrity":"sha512-4MwlGv4/GpuoRZ0G9ojfAPsNuT32tYeJU3nDE1ddcGzkduuIJ9Gw4yB1pBr+5nyKQKpR1fPsrh6pGdVTNsmh7Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIApgpxptc1jNOm+1LZ6hLcE5fZBjiCCf/gIyurgCLir5AiEA0raDtNyJo7GXn2oDBK5F15H4aXm2MPw6NfuW52kIzHw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26-alpha.10-sprintschema.tgz_1512015723763_0.22472863853909075"},"directories":{}},"0.8.26-alpha.11-smartgrouptype":{"name":"teambition-sdk","version":"0.8.26-alpha.11-smartgrouptype","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.5.3"},"_id":"teambition-sdk@0.8.26-alpha.11-smartgrouptype","_shasum":"008d5a3f08d095673f1fa2d4bfbc7d6e94cbaedf","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"008d5a3f08d095673f1fa2d4bfbc7d6e94cbaedf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26-alpha.11-smartgrouptype.tgz","integrity":"sha512-Q02N/yy3JJ9zKarw6k2HHytudmIEO9G+ptgjgRLchuQjc2TLThPcDUNL6baZQGnKTTIOV95gfpeI2K2fYFfyuw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD7JKL3U8S/M3o58nZ87faptM8wZdTBfhAwNu5df3fLYQIgcC3zEU2c44HG8PEfLNsSQyBGo4XwWM9rK1cr5+Bw0Mc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26-alpha.11-smartgrouptype.tgz_1512019611523_0.23940275399945676"},"directories":{}},"0.9.0-alpha.3-allday":{"name":"teambition-sdk","version":"0.9.0-alpha.3-allday","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"CST-8\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.3-allday","_shasum":"b0e04c0e35807414cc565f78e5e3c8fa0b760af5","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"b0e04c0e35807414cc565f78e5e3c8fa0b760af5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.3-allday.tgz","integrity":"sha512-m8z4aCVr55zPkapWD1EkvA//u2gjR/URnO4Huu92MrikKCCW4o9e2x6W2uprJvNS5k9/mstde91JwPhYxq3gUA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDybPXLvG8zUnjxtGhwB1oHSTtOLEyu/7OnW7GqsQhM6AIhAMYlHzruCm82OX8uQCP9owjT0ATk3y0VLZVmLDhr5phT"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.3-allday.tgz_1512035513493_0.7453985551837832"},"directories":{}},"0.9.0-alpha.4-allday":{"name":"teambition-sdk","version":"0.9.0-alpha.4-allday","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"CST-8\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.4-allday","_shasum":"4591fd9a29e9f534b8fc1274384822ce690ea15c","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"4591fd9a29e9f534b8fc1274384822ce690ea15c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.4-allday.tgz","integrity":"sha512-9v/O24Dbs799il957Jn/gFFASCkY0dTtQQXDn6xnRN7Av5P/m7IV4xnf0opUVKilgR5sFHl6jRUh641bTCgXNw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFIBhCthKiJ2K2827PQ8yUs9S5kO9irCndNA+zmSlUD0AiBEGic6wvmiLkWwDdrC+GsF2BBoQsgZvrggqKIFMVYA4Q=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.4-allday.tgz_1512094808759_0.9254222598392516"},"directories":{}},"0.8.26":{"name":"teambition-sdk","version":"0.8.26","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.8.26","_shasum":"630a17ffb47b1646feea0edfe4737ab44f552c10","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"630a17ffb47b1646feea0edfe4737ab44f552c10","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.26.tgz","integrity":"sha512-yoe3/hf7zUMN1K6uuOAWWlCUDIvmDWMj5Qz2H1h1+ARIe3KvAd8IUVLNQnn1MlrOgEQ2DINmHXRYXb14nR8kCQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDxJvDoQr9EQsuff+bHk0BpHPwSx+mcbXXIkxXre+UnkwIgeoESK28QmoTyXfHiiMnUGIqCLebC3q7PLhywi1VQtCg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.26.tgz_1512116992122_0.6421634776052088"},"directories":{}},"0.8.27":{"name":"teambition-sdk","version":"0.8.27","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.8.27","_shasum":"f8d4c2bb6da4a8a9d6e2e149b85ff684a6e32964","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"f8d4c2bb6da4a8a9d6e2e149b85ff684a6e32964","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.27.tgz","integrity":"sha512-fu988pw1BGxRLmw65PjRWTs8NW2qBiO+2x2nJOLh644t8UbsMWg6sKDWMhqjIx4pHcciH41Pt2RrpeEg3WbqOA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCzNDXNRWTXTgHEwk9ISTFEwHV8VoQckGti0wzpOY4aQgIgF4IYrKUmFfPJ1yU/DigKqZbHLUCmbglwgGKgHOJ+pWw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.27.tgz_1512443711726_0.5164741100743413"},"directories":{}},"0.8.28-alpha.1-tasklikes":{"name":"teambition-sdk","version":"0.8.28-alpha.1-tasklikes","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.8.28-alpha.1-tasklikes","_shasum":"f1abd036d0e4aacd91b053620b9cbd81c7c56cf2","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"f1abd036d0e4aacd91b053620b9cbd81c7c56cf2","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.28-alpha.1-tasklikes.tgz","integrity":"sha512-pb8qJ/3vhwVsLPpVZJ6Y1BDJauiJAXoHjdtevtj/3/M/L8ox10qkqCUPvwwUu2pR9uQ7+gDwnH6r1AzGTVXASA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCAXHV+2kR4girNXrmOuXwioh66lqqkMWEA0fH5Kl8a3QIgNo3saKpY/dz2sls9xsXSzcGTU1Es6BP5NK8aD4dGxFI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.28-alpha.1-tasklikes.tgz_1512579025363_0.4127237868960947"},"directories":{}},"0.9.0-alpha.5-allday":{"name":"teambition-sdk","version":"0.9.0-alpha.5-allday","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"CST-8\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20170910.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.51.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^3.2.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.5-allday","_shasum":"7c07e60c3307f220fed95f40ce39e20b33f664cc","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"7c07e60c3307f220fed95f40ce39e20b33f664cc","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.5-allday.tgz","integrity":"sha512-+qHlq9iOCsFiPt8rce7lw4Jm/PW+09HxNr7SeLLgtWAmP+fC8QIbD0ZaQxr8is+0DOzH3WFmqXt6n8eh5/W7IQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC/D5KD/Ovy/4ErbjFYsVQv12Fzl7YHpTAZYyl4Ce9pJwIgKPijBQuefs3MgqvICCPTTdvGnqnuZcGF9gpthBK5Hzs="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.5-allday.tgz_1512619417765_0.2586411042138934"},"directories":{}},"0.8.28-alpha.2-teammember":{"name":"teambition-sdk","version":"0.8.28-alpha.2-teammember","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.8.28-alpha.2-teammember","_shasum":"266cf9c05faf75fb4beb8a914a2f1337fe30a8d1","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"266cf9c05faf75fb4beb8a914a2f1337fe30a8d1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.28-alpha.2-teammember.tgz","integrity":"sha512-56phQ0pyrvZN6SqTa96sxKPWmchVY4ZTzWqagDrKhfqjjmdi65MGaNLM027/I/OMABbYHRMkBR2IlOX0RSe9vg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICubgCtZxVYfMbffHDuvRCoP1mA7fA41LkVEJBb/eIg8AiEAgVT3BO3iFi3SXJRQ2XOXqZqsWEMmeWrevUnp6/zHbHs="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.28-alpha.2-teammember.tgz_1513135858729_0.017442633863538504"},"directories":{}},"0.8.28-alpha.3-groupschema":{"name":"teambition-sdk","version":"0.8.28-alpha.3-groupschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.8.28-alpha.3-groupschema","_shasum":"6619fd07ac1070ebb7e40642485911bd944bb7e8","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"6619fd07ac1070ebb7e40642485911bd944bb7e8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.28-alpha.3-groupschema.tgz","integrity":"sha512-plsjCF8M429+6AU36L3PGB3gkc0EAZ0xvHU4r41ooyy9pXBNlpJfzopfrMX9Rn/PCCR700GwI6lKK+9WRZlYmA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICmCtNKZqmezDvnSngUCNSLfNeFkGdSJX7x4NpqHngcFAiEAmE/mUoPYFpAADyNGIl7z0D8+KuW5hWExU2JcmysSKCA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.28-alpha.3-groupschema.tgz_1513822648986_0.19414002215489745"},"directories":{}},"0.8.28":{"name":"teambition-sdk","version":"0.8.28","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.8.28","_shasum":"13da590635296f40bce34e8a64cde166ae66c126","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"13da590635296f40bce34e8a64cde166ae66c126","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.28.tgz","integrity":"sha512-IsrF5ieWvdwt9S/gWtcykuBI/cK2U7aSSQeGdTizSGszkA8PSJGYSJqMhyLgqYZ6d41j+fLgP2RzrrAE+cFRRg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCfqCiXwBJUF+v9+1G5baTosYwOqqBrxBqXmxzrteMavQIgWgjgCJESIsa8mddd+4gOFD7RDO8+QOVY7GeZYvIhoTg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.28.tgz_1513838673112_0.3714238691609353"},"directories":{}},"0.9.0-alpha.6-alldayrecur":{"name":"teambition-sdk","version":"0.9.0-alpha.6-alldayrecur","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"CST-8\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.6-alldayrecur","_shasum":"f814663fb022abe26a09a6a8beccff98954fddb0","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"f814663fb022abe26a09a6a8beccff98954fddb0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.6-alldayrecur.tgz","integrity":"sha512-qrC8ie2CcVzpqSOkj5Dsn7YbJbzKlSJgiMsGe+mCuxlc/WmNZ/7IglJfcnbWwYA00gXU+K2Pip6aG+HlI9e00A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE6SXMeFq9V9jV8OFJUoGBFS4lVcsZiDtsJYPIhrBgJ0AiBS3dinhzxOBDXK57Zv+EkznaSMB14sXbzncJlYTnlp2w=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.6-alldayrecur.tgz_1513920342752_0.18329055001959205"},"directories":{}},"0.9.0-alpha.7-alldayparse":{"name":"teambition-sdk","version":"0.9.0-alpha.7-alldayparse","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"CST-8\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.7-alldayparse","_shasum":"debdda0ea99c5de8de9c4401d336d9e3f3b5de5e","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"debdda0ea99c5de8de9c4401d336d9e3f3b5de5e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.7-alldayparse.tgz","integrity":"sha512-nIGmUbnzPBYNHRTSNE8abaXFUP6i8iniPWLx90JFymcVX4ZZUYQg1pMLYbH9uX4AdP6Lm6BOE9lZdBMKvP1RjQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFalDT+1UHDKzN89s/TEd0KZn+By7XeLkVC3l6qqw8ViAiAapGuNDivQQmyAjUQ8QjFw31cYGGmB4Uf+Sy3Hw1yY4A=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.7-alldayparse.tgz_1514190067156_0.8566348839085549"},"directories":{}},"0.9.0-alpha.8-alldayapi":{"name":"teambition-sdk","version":"0.9.0-alpha.8-alldayapi","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"CST-8\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.8-alldayapi","_shasum":"8ea2337689f8d4880f116c8e24f9fc0d6aaeeb96","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"8ea2337689f8d4880f116c8e24f9fc0d6aaeeb96","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.8-alldayapi.tgz","integrity":"sha512-ZtB+XjdEpE9jwcK5PqWYFQRAtzjckpTudYNLEeYSuCAXCXcenzzvIyTbrF3U1EgFMbFBgodUqFSiSu2QNWWPGg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDb+LjwdLWOd+9Imm+RRfaD6TP1mxJC0aUnTMYJvv/aEAIgTqweaR3XpCUL5sSROyCfG+dvum6AEF2GgvlLef7dytI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.8-alldayapi.tgz_1514363530139_0.67588249174878"},"directories":{}},"0.8.29":{"name":"teambition-sdk","version":"0.8.29","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.8.29","_shasum":"0ab08ce9ef5504c18fe7c5e291b86d16212caaa0","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"0ab08ce9ef5504c18fe7c5e291b86d16212caaa0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.29.tgz","integrity":"sha512-V+v2fmVxkDKFeoo7sNJTCz7dCbWyROszVzfxfDxBM5lIIQjNhTi5h0AMqdromZZdWNmH4jwUYRs4J/6fQI1dZA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAbLWCGxsZI+rQWXqmE35jsULkq6EpWOmVR3D3J2WPt2AiAQVcSQ7a2bFete2OF9qpQWC29FJlSYk7Rwc/soWbXVHw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.29.tgz_1514520253950_0.6657592114061117"},"directories":{}},"0.9.0-alpha.9-allday":{"name":"teambition-sdk","version":"0.9.0-alpha.9-allday","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"CST-8\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.9-allday","_shasum":"49b119fb3ee273f5ea0e20c5128b15f48790ef28","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"49b119fb3ee273f5ea0e20c5128b15f48790ef28","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.9-allday.tgz","integrity":"sha512-uQ0kRnn1pyLgGT5LQBQF3D+182r7NWTjImQbfc9672kdpbUpqnu8cAjwUUnj0ylhXiDDNPZSm6nUiGc0GqA0YQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCr+/2PrlWp9jw0pHJDdThkM6OZD1N0QMgirQXCyfzPJQIgAMV6BcVFIoRKDImDju7yVIazzB8dJSAuRtZOIG+mL0A="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.9-allday.tgz_1514540146641_0.20570088038221002"},"directories":{}},"0.9.0-alpha.10-alldayleaveschema":{"name":"teambition-sdk","version":"0.9.0-alpha.10-alldayleaveschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"CST-8\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.10-alldayleaveschema","_shasum":"7087c20e04dab8aa733453cf1e8b7c02da943a55","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"7087c20e04dab8aa733453cf1e8b7c02da943a55","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.10-alldayleaveschema.tgz","integrity":"sha512-+6ZzV2hYJvlfKdHSZ6tjFrZ+R1ugywyY9bbc61ciu+1swPaj47jaDEnzc70ltmoGnh83y2aa9WpmA7IccTiU/g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCTW1SumVAP1cicVbOYuan7ztjkv6f4jMjyhzoqVvBCCgIgZa5FPi9/zVrt4wex0h8lSW9jFfcvbqqARJsn+70PSgM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.10-alldayleaveschema.tgz_1514964833133_0.5862976175267249"},"directories":{}},"0.8.30":{"name":"teambition-sdk","version":"0.8.30","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.8.30","_shasum":"7571e3442ba6b761c322f988d4ebe2d41022b201","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"7571e3442ba6b761c322f988d4ebe2d41022b201","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.8.30.tgz","integrity":"sha512-wRa5FSsMNzntzYaky9HjlEKbSuQzAHj/8G+j5t7Q8J0X8mO4fGedHHhyOj1OUo8lWL0XhsB5+L5j3lkshdSIng==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEeJdIhwco+XoOt78lMiCjKeJNVZ5t+JaczOHKyG17moAiEAoPLxb7rFhReyX1jXnrh16x1fFtvAGHvVRqR6KUUVz5k="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.8.30.tgz_1515045343807_0.19648384675383568"},"directories":{}},"0.9.0-alpha.11-scenariosubtask":{"name":"teambition-sdk","version":"0.9.0-alpha.11-scenariosubtask","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"CST-8\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.11-scenariosubtask","_shasum":"f14fcaf34b0d649e20d360b6b98e5caa9785ae17","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"f14fcaf34b0d649e20d360b6b98e5caa9785ae17","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.11-scenariosubtask.tgz","integrity":"sha512-ButyXfli41E3SbX5uRBsHqSmpP5izUlRvDnIZOAZe+j/t4uMtWK1uSUGBwzy8hgSfrYoSNHftJSH7eRXfu4drg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB+RRjRwoB5TOlnD8PV4Pr6MV67Qf+SGviWGYcaPxYMSAiAgoICHKzcOpbSNJOTRlbOxAeKJXHsYUJkJvDChGtArZw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.11-scenariosubtask.tgz_1515048832820_0.5502441222779453"},"directories":{}},"0.9.0-alpha.12-nonalldayattrs":{"name":"teambition-sdk","version":"0.9.0-alpha.12-nonalldayattrs","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"CST-8\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.12-nonalldayattrs","_shasum":"99c696d3dfdfad3e4d384946f6579160442e336b","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"99c696d3dfdfad3e4d384946f6579160442e336b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.12-nonalldayattrs.tgz","integrity":"sha512-to+J3TggKBvO90uB0kH2Z/WdWYADef3MkDE1CRTqSJrANI1sCgqxZtsPk3eJ0AqrmVHF0zesCuzR4no5N1eckw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCAnyLpf+GZYke6jjgnUhExxQdcWg7/XXSQX5nOWpBizAIhAK9cXB0jHpyTA3ZLh/pxOJ9aDxpVIr63qiQtkbQycRfF"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.12-nonalldayattrs.tgz_1515059378889_0.9803097825497389"},"directories":{}},"0.9.0-alpha.13-datetotime":{"name":"teambition-sdk","version":"0.9.0-alpha.13-datetotime","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.13-datetotime","_shasum":"058cf7bd79931c1d3297a50ddb6681ca1b1f67dd","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"058cf7bd79931c1d3297a50ddb6681ca1b1f67dd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.13-datetotime.tgz","integrity":"sha512-TCgqt5D2WjgyUvcxGxsc5fxPPFpZT5cKtScwQLW9G7tJJN0gx/uXF5Fc994WloK09tCzYl1aP2ncwbuGGvPVCg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDp0NTTyGGptMbBdxYtRNocSjePrDnqrwR8Xe8rq17OSgIhALkS4o1l4rt3tmjdIKLEOhY0XB5G/Zg28AhjWt2bKvXB"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.13-datetotime.tgz_1515082780790_0.12615460203960538"},"directories":{}},"0.9.0-alpha.14-teamschema":{"name":"teambition-sdk","version":"0.9.0-alpha.14-teamschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.14-teamschema","_shasum":"f70d524a569050630ffa0b646658ec3d62d8280c","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"f70d524a569050630ffa0b646658ec3d62d8280c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.14-teamschema.tgz","integrity":"sha512-HgyTRgyfll7zcf0Fb9Nq9SUyISf3NHkdit3oA0CGEZXlW/87zxqG0s+4WDl82gzxivAJBPcKW3BcBDBDmv8Clw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDH45AHUYFR91EZL0uLbx5MgrdPElgf++wa25kmj/5e1gIgOXuoUQR6J1/trLpKcZ8+hBN9LUaOxAx6kTwhpRUe0y0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.14-teamschema.tgz_1515142164623_0.2925566635094583"},"directories":{}},"0.9.0-alpha.14-sconfigsubtask":{"name":"teambition-sdk","version":"0.9.0-alpha.14-sconfigsubtask","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0-alpha.14-sconfigsubtask","_shasum":"cae5da81c96babe4e37a29059b82a921412bdf07","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"cae5da81c96babe4e37a29059b82a921412bdf07","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0-alpha.14-sconfigsubtask.tgz","integrity":"sha512-KceNGkJ/ZPLHW+PaMQVHyHyi9bJ5oxNmNqnSAkj38doi2IGNOXGYzaOp93IQ1JWkR5/Qjhx5267WSbXzmNSVxA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDw+gcxISk+tQlyyz2agNLVRs/pbawIWDDmvw0HPWY8WwIhALgoH71xix2MVnlHl3XWEVPnKJwvAF/0FF9HIiGjrMyx"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0-alpha.14-sconfigsubtask.tgz_1515583691082_0.1523508015088737"},"directories":{}},"0.9.0":{"name":"teambition-sdk","version":"0.9.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.0","_shasum":"37e017950cf5ccedc7cb856c79f434749ebb42e7","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"37e017950cf5ccedc7cb856c79f434749ebb42e7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.0.tgz","integrity":"sha512-BgFcMYJHESEqSnXYtjhbIQyNTfyRn/eOvU7o2zVx68rpuijIJRuZrH5EZbmoAeJ6a8PcVIRKnxJ5IgniVSp9RA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD3HUI4iaJXAus6XRwRHx6I0FmYQcw6DhFOJFuA5z5cDgIhAK+jFKpJwAFetzNSud/dvfgnifgqhoUFOmsnxPfNNT4H"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.0.tgz_1515670641343_0.2232861912343651"},"directories":{}},"0.9.1-alpha.1-teamschema":{"name":"teambition-sdk","version":"0.9.1-alpha.1-teamschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^8.0.28","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20171203.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.52.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.1-alpha.1-teamschema","_shasum":"2d0a3923a3010b77fc64eaaadbc7859f6d2a9841","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"2d0a3923a3010b77fc64eaaadbc7859f6d2a9841","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.1-alpha.1-teamschema.tgz","integrity":"sha512-G2YygEGwzw4Ttw/9akX+dinU6PInYgVp1sWsX/oWgIFTx6wDp85ps5xAcLR5tyfQ3TzFzmiMKvVgf3TCnkrQzg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDfrMoXbw6MFlM2ItxRmKaYAmnL2REpqtuSriGXtoqDFQIgB5O5DkEROp0IEXT7/IMcZ6g6KcNWI0xOVADLFflL+yg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.1-alpha.1-teamschema.tgz_1516069974233_0.5875539414118975"},"directories":{}},"0.10.0-alpha.1-wsmidware":{"name":"teambition-sdk","version":"0.10.0-alpha.1-wsmidware","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.10.0-alpha.1-wsmidware","_shasum":"dfb5eba459684792678f984b6ff0d93bdd0406a6","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"dfb5eba459684792678f984b6ff0d93bdd0406a6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.10.0-alpha.1-wsmidware.tgz","integrity":"sha512-3l0z54FfOkmDDz9fdNhjxoXJ9mJ8vpMEt/cLV7fkGpzi1kq18To0uhCJr4cxYOjzGJh3P1oSWzNW/iqRwRdiLQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCSPYkeni/PwEesJpilF0n7sSPWi6na1lMFk0MHYe8yHAIhAPyHzYj6j6SV0YkniH7Xi31r+GKpFlZnFtbl1BJysO0b"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.10.0-alpha.1-wsmidware.tgz_1516763153068_0.5270957045722753"},"directories":{}},"0.9.1":{"name":"teambition-sdk","version":"0.9.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.1","_shasum":"4e1c628247075ae6c971a93f8ee19ab65700d3a8","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"4e1c628247075ae6c971a93f8ee19ab65700d3a8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.1.tgz","integrity":"sha512-r0JrsmtcdwClXpFv98x6WeDNXTSqxdl/RTAMrJUs6nI1zfF9jh8IyaSIpnI5Bml17olLoL5X8t1nmBCcxwD7tg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBxEPG1j1Fd3Q9cJVIH6/wH/7OVtVtWNuS8sr5dy01mIAiBKr6v68smm9D8DRJtS4+oJQqAJlqrlQH1RaizKLsKWtg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.9.1.tgz_1516957334049_0.41820080298930407"},"directories":{}},"0.10.0-alpha.3-wsmsgfix":{"name":"teambition-sdk","version":"0.10.0-alpha.3-wsmsgfix","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.10.0-alpha.3-wsmsgfix","_shasum":"bd055594842b3762da4c6a9ed0026a409134b4b0","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.10.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"bd055594842b3762da4c6a9ed0026a409134b4b0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.10.0-alpha.3-wsmsgfix.tgz","integrity":"sha512-ko+ELSQKY2xAgc/Yt1890Ib+0Wv/ALCKEcMuE08R9+hu/+zTHLYRyFydgLd5SmM4r01EgR0cqBVQJKWQbu/zLA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDKzTOVAoupMmW5QFWq89K+PXYMnf9JYzVlSA3fZkES2QIhAMVk3U0gXiLKAUXRBf8TWsx44TUpg7Pj/yrgKS+OJC60"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.10.0-alpha.3-wsmsgfix.tgz_1517284494877_0.355757734272629"},"directories":{}},"0.10.0-alpha.4-wsintercept":{"name":"teambition-sdk","version":"0.10.0-alpha.4-wsintercept","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.10.0-alpha.4-wsintercept","_shasum":"489a8abb42bdef1921e42ada88e7984f2544b1af","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.12.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"489a8abb42bdef1921e42ada88e7984f2544b1af","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.10.0-alpha.4-wsintercept.tgz","integrity":"sha512-35zVHNi/NWiu3gfeQ1s4/5sx+arYD5BIKDVJWaPITwmKIWrcJIPPXIoaw0+kZH3YrjWkjHN+y0Nd0X7OP6S0Pg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA+gsjsP7+biE/Kn5cx9wq9qnieHD+3l/aUFP+4mOJP0AiEA7XaeGxCH5nHCulsxrH0WomDb6y5KnM0SWvNhVTs+nLw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.10.0-alpha.4-wsintercept.tgz_1517392924300_0.2922515196260065"},"directories":{}},"0.10.0-alpha.5-wsrefresh":{"name":"teambition-sdk","version":"0.10.0-alpha.5-wsrefresh","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.10.0-alpha.5-wsrefresh","_shasum":"3e90bb9d40a5f2fd54006cb84fff9be949b9acc1","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.12.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"3e90bb9d40a5f2fd54006cb84fff9be949b9acc1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.10.0-alpha.5-wsrefresh.tgz","integrity":"sha512-SQVd/LXejVxsMUlIS8q5ykHbEsH47h6mNAOkdeF6HQQrZMM6xguWST77k3460jdAK8BsB5OX2uwpgxH5LxKgQg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB4nQcxJOkrDYudwdXHFKXq8XAthITI88t9YE2nu3SomAiBWnFzOIivwWxcb2T/Swe2BYVA1/SsHXaxctRlPwahm9w=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.10.0-alpha.5-wsrefresh.tgz_1517563338187_0.29875351837836206"},"directories":{}},"0.10.0-alpha.6-wsdeamon":{"name":"teambition-sdk","version":"0.10.0-alpha.6-wsdeamon","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.10.0-alpha.6-wsdeamon","_shasum":"ecce519d110f5a35b17ba06c9d0f03ab43d83645","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.12.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"ecce519d110f5a35b17ba06c9d0f03ab43d83645","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.10.0-alpha.6-wsdeamon.tgz","integrity":"sha512-ywzalBO3cbQKAUGrbmR4HELx4xXsBddqqCHaB3qrcrZDR1+dmK/pHfDGW2JNe0ekSpK18cD2Ml5Y6ba1H/wxmQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCBB7F+WrjkaEaZ/0yCAL6xlwNchvGmjD4xDXUr3OGHNAIhANoOabAyH8tV3SRaTrybdhZvJC3vqbSC7I4esqp/hBHA"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.10.0-alpha.6-wsdeamon.tgz_1517836765894_0.3660524857696146"},"directories":{}},"0.10.0-alpha.7-wsonrefresh":{"name":"teambition-sdk","version":"0.10.0-alpha.7-wsonrefresh","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.3.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.10.0-alpha.7-wsonrefresh","_shasum":"1df15279094dc61adb7cacf8429096ec5c00c69f","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.12.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"1df15279094dc61adb7cacf8429096ec5c00c69f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.10.0-alpha.7-wsonrefresh.tgz","integrity":"sha512-JrPnHXqYhN54UWdwZ8TuLMn+ds5T0uKt0Y+I2RQ2YArpNExZzjK35cswTfzDlovMoCqtL3WqbgHIYDrcu6/WUg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDEaDGF40Ymg64efNUY/CfVefMVvXgc2r4j46bbLXeK1QIhALUa6oNt0gDQtvaqqGMtv4+AGe4aja66pc6UXIHQKDlQ"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk-0.10.0-alpha.7-wsonrefresh.tgz_1517903115431_0.5774160660803318"},"directories":{}},"0.10.0-alpha.8-socket":{"name":"teambition-sdk","version":"0.10.0-alpha.8-socket","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.3.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.10.0-alpha.8-socket","_shasum":"87c35408f202b86b98fcaa7e8dcb9afc9dab7900","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.12.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"87c35408f202b86b98fcaa7e8dcb9afc9dab7900","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.10.0-alpha.8-socket.tgz","fileCount":305,"unpackedSize":633453,"integrity":"sha512-fcjgaJzykjVKhhg5cABn49G5AiCAlROzUaMfQP49XreRkgm2iaVuaCugDImppni5keAiket5++/a9yfv9NG56A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFpRsSbFja2t2IeWmshAwHCF7C6HaoV0jK+cKswG1PwhAiAEr2DjvrztwwkcS14NRTuyVNOJ2m5QXZhh0O1EU/BdRg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.10.0-alpha.8-socket_1518061913688_0.6503245587889444"},"_hasShrinkwrap":false},"0.10.0-alpha.9-wsworks":{"name":"teambition-sdk","version":"0.10.0-alpha.9-wsworks","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.3.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.10.0-alpha.9-wsworks","_shasum":"5a8eade32dae91928f034d7c237ee461c3d149b6","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.12.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"5a8eade32dae91928f034d7c237ee461c3d149b6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.10.0-alpha.9-wsworks.tgz","fileCount":305,"unpackedSize":629440,"integrity":"sha512-ArRs/Kj6lSmwLSEVZjVrkiItrdC2xvOuPT5rajjs77mENF1RZuqM/rKmDMIAav8e2DBJPY6N6YGOWq7fBCgLVA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEckxUOfMsnIvBoHobeITcTdn7F9m6dxsqM0niCJw1XiAiEA1uGEzyoZgxhmH04tJljcSSSH62O+p462hJ6XesFGBdQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.10.0-alpha.9-wsworks_1518165002916_0.29114487384029686"},"_hasShrinkwrap":false},"0.9.2":{"name":"teambition-sdk","version":"0.9.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.2","_shasum":"4ddcece52f081ef9a00bca8ccb3b66dc521975a8","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"4ddcece52f081ef9a00bca8ccb3b66dc521975a8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.2.tgz","fileCount":293,"unpackedSize":589023,"integrity":"sha512-uRzyB0V8LaX5Fc3J0g7hddGmbO+qFK1DskzRkZcXBrM+AnZDb0rCBHTAJa1GkxmYnyIwZzLTC3OwHf+AcXrQRA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE1BUMZrSaDvMGayOWPvW1wqBAVU5XwWV6Rj3JaVxDtfAiEA1l3fif0TLjxTLxK7DU0XaG4W9LgWApiBvLGVLwiaXbk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.9.2_1519870304167_0.51862984299032"},"_hasShrinkwrap":false},"0.11.0-alpha.1-taskflow":{"name":"teambition-sdk","version":"0.11.0-alpha.1-taskflow","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.0-alpha.1-taskflow","_shasum":"2337c0ac2dc2c888e920d920cd32d09d13273630","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"2337c0ac2dc2c888e920d920cd32d09d13273630","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.0-alpha.1-taskflow.tgz","fileCount":299,"unpackedSize":596229,"integrity":"sha512-RsdlEdEAd4yuwjpz4P2gxQWn8seUENNyI3ZUe+30hLiGiyJoF1D36B5c5ulxDVN3K7wx9aZliGUH7lyTsB42lw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDwo0O9L/kaLWWwYFFhs1v1HPcwaT6UPhrmhHCsQ8U0GgIgXkcBoOVR3RfBl/6tIjn2r6LBifG0XH3PxJSGlw5o4I4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.0-alpha.1-taskflow_1519959754098_0.27030256283441423"},"_hasShrinkwrap":false},"0.11.0-alpha.2-taskflow":{"name":"teambition-sdk","version":"0.11.0-alpha.2-taskflow","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.0-alpha.2-taskflow","_shasum":"01cde6c8193d2630c41691365834ce8935a201bc","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"01cde6c8193d2630c41691365834ce8935a201bc","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.0-alpha.2-taskflow.tgz","fileCount":299,"unpackedSize":596412,"integrity":"sha512-kjHPG8bxxZJE+siy1YqMm6ptOzSuM9TozJQ2+HXzgF8BklqQgNwf0wll97Zx8Kl32WWAgXM+fsfohIPNBaqxLQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHohCITY7tk1iX7BeXzyomqWnB3kynRh8vxTHSrnlReHAiEA1IoPai64Dcos2KEuceriXUYt0FRBjEBznT8tTnCn/ws="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.0-alpha.2-taskflow_1520217504080_0.0884168746483851"},"_hasShrinkwrap":false},"0.11.0-alpha.3-taskflow":{"name":"teambition-sdk","version":"0.11.0-alpha.3-taskflow","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.0-alpha.3-taskflow","_shasum":"04b051feb3d59dda90a7e961143b87cbe4308372","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"04b051feb3d59dda90a7e961143b87cbe4308372","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.0-alpha.3-taskflow.tgz","fileCount":308,"unpackedSize":606026,"integrity":"sha512-9556EqfMgdHWWfn4LPJPX5AfDLPJNFLE8OvpAsQqhnIHohyqzJ2wwIQkWPqffUThA5F6YmoezAUdbeyzFGs/Vw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGkkxPVMNx/uPwXGohGxn96jrbzTpcKVCZgSA8S60FdFAiEA9H3yapzKl3OZZuko3ujmmBr2ek8SSJBXuo3hjzeZ1tg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.0-alpha.3-taskflow_1520498971792_0.7032555495638841"},"_hasShrinkwrap":false},"0.11.0-alpha.4-taskflow":{"name":"teambition-sdk","version":"0.11.0-alpha.4-taskflow","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.0-alpha.4-taskflow","_shasum":"dd6b02fd316aa44af68c200a32a9f1d274cfa827","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"dd6b02fd316aa44af68c200a32a9f1d274cfa827","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.0-alpha.4-taskflow.tgz","fileCount":308,"unpackedSize":607311,"integrity":"sha512-hbnW9388jxUdl0QqgqLfGaPeZNF21kSz1VRSIdy31392ldCdH6cnQ019W/JM294UlnpRbMfEjPK7Jf0qPgbRVQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDTuT2n6IoayG9Ool53fQ27wWT/tEMR/4r+9jjsM7JpSgIhAIKftxWvwZrO0hc56Ip8Gk4rXFrII3XE5sRLrHP/0gtQ"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.0-alpha.4-taskflow_1520823963083_0.6654632469626749"},"_hasShrinkwrap":false},"0.11.0-alpha.5-taskflow":{"name":"teambition-sdk","version":"0.11.0-alpha.5-taskflow","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.0-alpha.5-taskflow","_shasum":"74ae7ebcebdd09983eea5b47a659c1160899e820","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"74ae7ebcebdd09983eea5b47a659c1160899e820","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.0-alpha.5-taskflow.tgz","fileCount":320,"unpackedSize":615157,"integrity":"sha512-PKPj5/05Bqt0qFkf7MM1D2OJYsf8LpqYxz4L4Ojot6/Sm6DSpTSQixtAqczkh+h2tBYmeQuQPYci/peJShOaSw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD80I7RCEiWpA5ETFGJyeFTn4nCezE0GVKYZM4f0W6ZOwIgKy8rj0eDh+liFkjr3pBfdmrpAeiGWthP8rYH22uyE0M="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.0-alpha.5-taskflow_1521019496507_0.49575425621264047"},"_hasShrinkwrap":false},"0.11.0-alpha.6-taskflow":{"name":"teambition-sdk","version":"0.11.0-alpha.6-taskflow","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.0-alpha.6-taskflow","_shasum":"7ab73b76f1a7699d3722eb8887ce2c3459d5cf01","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"7ab73b76f1a7699d3722eb8887ce2c3459d5cf01","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.0-alpha.6-taskflow.tgz","fileCount":320,"unpackedSize":615513,"integrity":"sha512-4+v1vGlGmw60OxG/us/DKzwIxTJaP9h55jo1WoDfxjw5ZpESitUv+cOyE9LwlJ5oAkJ3OfiOGvFMVN9Ijyd0bA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC7HX96TpE44iV25W/JQyFmw45W1jramQzzzpkFeH5CDQIgQaP6z0443TI93nw7lfwSGE0RYeGZyrJLQ94kLahrw78="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.0-alpha.6-taskflow_1521173687475_0.6256617488816272"},"_hasShrinkwrap":false},"0.11.0-alpha.7-taskflow":{"name":"teambition-sdk","version":"0.11.0-alpha.7-taskflow","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.0-alpha.7-taskflow","_shasum":"51f265b730119b857c3d9811f867c5c4746fd346","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"51f265b730119b857c3d9811f867c5c4746fd346","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.0-alpha.7-taskflow.tgz","fileCount":320,"unpackedSize":615742,"integrity":"sha512-uxct92DekqXSIaP8NC1w+M4KsizjyYq3fNjiVsvU3uS2R/SdahImcx45AgA4cf9T3aJCfgwbqiVK0iNgSoc4vw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIANMtXPj3S4aMOlSWhPOQt82sDW1oB9pUiV0NrlSeeKoAiEAwsDFh02Aom5/h/rHBDRj/0u171jAHD4OWmWrB18PX8Q="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.0-alpha.7-taskflow_1521446933384_0.0949697366283968"},"_hasShrinkwrap":false},"0.9.3":{"name":"teambition-sdk","version":"0.9.3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.3","_shasum":"58a66d38e364554c9a51a7b29f86a7a839144008","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"58a66d38e364554c9a51a7b29f86a7a839144008","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.3.tgz","fileCount":293,"unpackedSize":589319,"integrity":"sha512-d+eghqkRlFPGa88d4ZoPg/Cw9WGuypg8xobzzQGqbKJI9qMj5ndVLsIo2gpJaWEsiTO4EtgIr/SC+7pOKF1HEQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFF6eTEPe9rXQ0MIZQimF/KyaIYQcb/Ced86MfOiEU9DAiEA42uSwC+AIoxF7b5e1Ka+qVDEz9oelsUbpMTy2TYHXVk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.9.3_1521458782853_0.20598007358953985"},"_hasShrinkwrap":false},"0.11.0-alpha.8-taskflow":{"name":"teambition-sdk","version":"0.11.0-alpha.8-taskflow","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.0-alpha.8-taskflow","_shasum":"73836b370ae24cb5f6a12e5d2c5aa1a35a37bea2","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"73836b370ae24cb5f6a12e5d2c5aa1a35a37bea2","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.0-alpha.8-taskflow.tgz","fileCount":320,"unpackedSize":616038,"integrity":"sha512-ijnC8+sJZCH6KCYSwAyHYz4FfA/JAUIZ18rrfo5CxNaMK0RltshTFwDJ0Ft+FZZk4t2XB38sF6rmIM83+b6UgQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEUvsE86v/HPeSbrJtyHPnprSoOgZKvy+LfJVMfxTCDzAiA8b7Dw73RVm7SoG55sso9uuKpMf5EFeDwm8V5ZAUbybQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.0-alpha.8-taskflow_1521531094467_0.5445111759142633"},"_hasShrinkwrap":false},"0.11.0-alpha.9-taskflow":{"name":"teambition-sdk","version":"0.11.0-alpha.9-taskflow","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.0-alpha.9-taskflow","_shasum":"33427f123ea9bdf52df9dcf0525940e04c0ba07b","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"33427f123ea9bdf52df9dcf0525940e04c0ba07b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.0-alpha.9-taskflow.tgz","fileCount":320,"unpackedSize":616038,"integrity":"sha512-KpS7TOVdOO1tlvJB3NpZxik+WfNwzEEwMRJKBgZSHCNJaVXQuUJ0axAeGRF7WzUPdcdZwt4IlEdDR9/H0G+HVw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDV0JPsJmWntavQZUoCAyk/6j1CgVb4z9g8Z/ZQekpaKgIhAJHQEdEGJY70z44q/Egam+VQBT4GEaldllkbdZkt9KiY"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.0-alpha.9-taskflow_1521534295254_0.5319872894147766"},"_hasShrinkwrap":false},"0.9.4":{"name":"teambition-sdk","version":"0.9.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.4","_shasum":"ff8d2da5dc75160cfc6a5ccf607e8e8f8686a79b","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"ff8d2da5dc75160cfc6a5ccf607e8e8f8686a79b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.4.tgz","fileCount":293,"unpackedSize":589940,"integrity":"sha512-MfUj/vo1vo+tSTLcfrbWCWfXw+SGSNboiH2zvQMILslg1dT7YqF+dvJYHLakH5dej2h8jhg2CzD+TCdbCicwuA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID3IaHEVQwTvEHdlNQRbvSB8vRny8F/60msfTeVEQZEPAiEA8ZG267zvzOvGSAFoQT/joZIAib9fmwIT12zsuCzO430="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.9.4_1522055328245_0.8903130896944809"},"_hasShrinkwrap":false},"0.11.0":{"name":"teambition-sdk","version":"0.11.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.0","_shasum":"cafa001878d8913c2f6b225852710ee192825abf","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.13.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"cafa001878d8913c2f6b225852710ee192825abf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.0.tgz","fileCount":320,"unpackedSize":621369,"integrity":"sha512-laqa5uFFv9kRzjLMBu9RKP1vkMcWkXg8Ooy/MaoAm89LPyp3HPDawLya/yF5HktN9Gzsjp7X1bsoXp4F0yAeGw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD+e+PXwWMQrYNPO63T9/MwciMvzL2Tq3xO36puEn4SKAIgCHzFIBF4R4orDjOmyf9TWWXrSeGN0EARtoliZWcqFg4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.0_1522229600378_0.39183727109475464"},"_hasShrinkwrap":false},"0.9.5-alpha.0-httpheaders":{"name":"teambition-sdk","version":"0.9.5-alpha.0-httpheaders","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.5-alpha.0-httpheaders","_shasum":"4e163bb2951d2856f73f306a28b8d3676afa5c71","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"4e163bb2951d2856f73f306a28b8d3676afa5c71","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.5-alpha.0-httpheaders.tgz","fileCount":293,"unpackedSize":589763,"integrity":"sha512-wzTlQW5Npi1jRFc3iicOJbL+mNvGGyZWEAH91bAcVFkIzvTziayNdUKJF8jgZ0jQTmXgnwpxgaG5O9ytnMyiOA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHB2ZyAUO1nj/EyxUU/mjed6hNJ/eV7NPAWAcgkrkm+sAiEA2JmJSVv52sJNBtIXwMt31RmPEKkB/AyDisVOe86yV9k="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.9.5-alpha.0-httpheaders_1522405037435_0.6024279633419038"},"_hasShrinkwrap":false},"0.9.5-alpha.1-urlencode":{"name":"teambition-sdk","version":"0.9.5-alpha.1-urlencode","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.9.5-alpha.1-urlencode","_shasum":"fa82ce11d800f87b7e9ee43cff7a8088747e6177","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"fa82ce11d800f87b7e9ee43cff7a8088747e6177","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.9.5-alpha.1-urlencode.tgz","fileCount":293,"unpackedSize":592280,"integrity":"sha512-L+mNXnUPivDEPw7Y30pmpIQBLPAi9H8/dgyLs/pagpy/v9DUUoAGL5bmMOsY4LvugiLchQB1bbOoJIXdqV4m6g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE5rFkK4eEFGC3bMK2LtlIcD+hiI5wbyWT5veGwWmLqgAiA0soU+bAW7tDUluuB8k7LBd4emxi/PqfwkRY7BgFrGZw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.9.5-alpha.1-urlencode_1523417190598_0.4200563587635502"},"_hasShrinkwrap":false},"0.11.1":{"name":"teambition-sdk","version":"0.11.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.1","_shasum":"44b10684dc38b2791fd964e62ca7c83177ecea89","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"44b10684dc38b2791fd964e62ca7c83177ecea89","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.1.tgz","fileCount":320,"unpackedSize":627787,"integrity":"sha512-oU0KtEgVL7VvKxtGGkLh4IG9s5Iww2qKnjILzzbSqIa8wb7bsCrQRksuHl+kbJgDkdTx3z6+yj9kcZJX0zrqIQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC+Vy1r0clcjKuf1W+A32gL9spjxtKIJdKBtRwO51Q2lgIgNg46tpnVLV986H5V+qlONkJ1NUtd5fD9Yzey272IZPE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.1_1523425178646_0.38075661150187656"},"_hasShrinkwrap":false},"0.11.2":{"name":"teambition-sdk","version":"0.11.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.2","_shasum":"a5c9e37bce8701ccfaf36cc9b50bbaf54a6d1b1f","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"a5c9e37bce8701ccfaf36cc9b50bbaf54a6d1b1f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.2.tgz","fileCount":323,"unpackedSize":629223,"integrity":"sha512-Jy2DJNkRfSJjMOrn/zgPlBsUKzUfFDEc15L21a0CEDgrYzS+IOAPJrjwJTupPa8LdLJuv+b9RGYi0sa7Mr5TqA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH8HD0+RBAOkWWeZvIuVW81HFTEMHenbF04ludr8T8NUAiBUqFl+lTpLc6wlJg4sYjutJqvuPotG9Tth58zfAz6FOA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.2_1523527350980_0.6224955777179215"},"_hasShrinkwrap":false},"0.6.12":{"name":"teambition-sdk","version":"0.6.12","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --isolatedModules --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.3","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2","isomorphic-fetch":"^2.2.1"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.4.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^2.0.0","tslib":"^1.7.1","tslint":"^4.3.1","typescript":"^2.3.4","whatwg-fetch":"^2.0.0"},"gitHead":"401daea89b3797199e6bceaf9f70a4bb4a02d59c","_id":"teambition-sdk@0.6.12","_npmVersion":"5.6.0","_nodeVersion":"8.11.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-aTaFqTPbOgcF4FQoJHYmqnUDNAkCFX8jZWjJoJ6UM0piHorm5V9yL6m4YyG3I3QqQblnQ+BDo1uUtHMcJ/tPaw==","shasum":"0d2505b13b00f6e7c99d1676b2e45463ee051dcf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.12.tgz","fileCount":1103,"unpackedSize":4267886,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCWM5EOrIlsGD/CrFRDoNo4rI5ROGgKI4vJyZQlmNoFrgIgc3GRcpgdwGYY+HgMsgRpqVIx9v2vULH8XuyLeJUcpdg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.12_1523625051036_0.9156990771461735"},"_hasShrinkwrap":false},"0.6.13":{"name":"teambition-sdk","version":"0.6.13","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --isolatedModules --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.3","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2","isomorphic-fetch":"^2.2.1"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.4.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^2.0.0","tslib":"^1.7.1","tslint":"^4.3.1","typescript":"^2.3.4","whatwg-fetch":"^2.0.0"},"gitHead":"aa2cb415ac173d916aa1211a91dad396530a2ff2","_id":"teambition-sdk@0.6.13","_shasum":"e0d97ba51614a2f7d782a6bf68471defb3e8e57e","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"e0d97ba51614a2f7d782a6bf68471defb3e8e57e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.13.tgz","fileCount":1106,"unpackedSize":4272551,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa1u12CRA9TVsSAnZWagAAQM4QAJ2CaPfK7dIdltjjVHiF\nbz/nELmkyUKx3yaA3xqd8aRlEXE4kSSVbQCn/Sybec1ir1I1SHivFbJhqLeM\nGSvJT/mR+wZcSmUf/cZU2QEzLKn12fL+05JJsTyQBBPbO/LqhbYUu11aKn6t\n7Z8rijRIr3qikChwMBZ/UN2kcUUDz3pL+qXDm7b8Hym6uM+iAljv9WWFoU78\nb5EAZJAPTUqtCleW2VjhggQN4ptRijqDGbQVi7l1Fs32xFwcGxrkgIqkeI7S\ngTrCOp8sHggWBxXdtf51qIifHt9EDU4RE3Rvms6k9MLFZmwsM84bMg1yYiud\nt4N9Nb4jpA76h7OI2l2T8oRpjzYV81pONkZz8Rfeb7t7Bu2lJr2koKshfyzB\nn9ZOLde+E/OGHqULdXyZ9WmILxg6tVx4am2oaOuhC1TA4MPyf7/yNgZw1ZQ/\ndvkzlYdUu8SPZnMKJtjj2nriXsT3zj/wy/sUkdES0d39g4XzhM9FLmZ2Gfn5\n9NWJsED/6Z8PaHtGbKUVT6ePaqcI1c2o2P52hLIK//Uo3qEgQPWzdhaS4a0M\nooDC0hvhT0Jr+piDuTXYjdLUphXISjn40IpgJq0nNvzXwzEbvCTdTkDck0jD\nqQHmjZ4bLd9irVOErMrQOr7YD4qwd++l1YYqtd+uRFtsOXEefQFPYin5Lb2w\nBWOh\r\n=xHZD\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-uq/VmtchdD7lRxcGNDQuaV6Dlci01l9ExUD7e/H/7kO4I6zNiwF18xixhDVi7ERXWxm2Gecc/JR4m0cAYallVQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCvGS3wiYgAIrPXa8VxF+/g14XUVgNyyRKk+We4NciaHQIhAISRrkTDtKM9QflIk0fHYyNvMmjM+ex1corbiLNOS2e5"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.13_1524034934118_0.8254264560391245"},"_hasShrinkwrap":false},"0.11.3":{"name":"teambition-sdk","version":"0.11.3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.3","_shasum":"f7c6ab362513c794b5db610b74f4ece8656ce449","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"f7c6ab362513c794b5db610b74f4ece8656ce449","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.3.tgz","fileCount":323,"unpackedSize":629633,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa2BT9CRA9TVsSAnZWagAAayUP/3FD71tD7KfkaZgl8LsH\njoiUPNH57uZqniIPb7BIrogPL4iACQQH8Y7QksWyf9pvRhfeVwAie/4C10Zf\n4SElYTQJ9qXzSAxO3dEUqOYbihBjCZpbrk1WtJklcXSR0hm1rwKUS/m/V0qf\nuSJKzqqi2GWc4UjEg0t9nzzjTAxOssRuX4UZAuTuuOx5KQclYi5Dhkx/GhZm\nC3G5PlXNmUlfNtB/BvAYT3cemT2S4UxBUVsgredynCr1aMCT+H3fxmDSlTPh\nFPlMd1CWQKp18OZintueQhcwm9L77s0aMxjJTSX89r7NUdatd7rziRqgMYYM\n1h6O6Md78Iqq/Vj2+QzAsox8vxSl2/1zBwRzBWihgVl6P3kv/Alu30wQSOCH\nBW2efZB6is9KcBfeUPNV25S7bItQCHekQ8uAgj3cIY6CclZMzIWTx7f2B7u3\n6OwKed5l648odySyZqm3SFQZyFOHWZG3oJPKByFHZ8U9lMC5z2TyMjAKlIQr\nh59kQxBAqC/0TogKKD/EdUmH6It66X4LxAvv8lOIGC1d0zTntW1XpVJA1QyY\nSdhH0e5D/v58PYW3PDArMIIC2VQPJ78gmats4nnEu+sDX6+yBZHngU55RUH5\nzqw78vATivvXy2Djo5gGpYcgT20wPxRS+7CkENsTP5Ec7z2YoEnBrSK0KpGm\nL8Kk\r\n=X6ZV\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-f1hYqTwHDclyi8JuiLcBCfG67IKMMXX/bskMOG/F/QfiXOoMLqulUqrXxOe5e6OVpQ1SG3K8cXlqX4A1Sw1p7w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD/iQ82G+Hn0G3n8M/ZT/33dz6krVZ9xYaXiVOY5ghaEQIhAMBjC0KxyEiw90jphBPX+IXzmVT+LtFLfX8SYJjjOEtx"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.3_1524110589118_0.4127122110686763"},"_hasShrinkwrap":false},"0.11.4":{"name":"teambition-sdk","version":"0.11.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.4","_shasum":"53c74abbc99d87568de2c0c06219384c11ef1d5d","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"53c74abbc99d87568de2c0c06219384c11ef1d5d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.4.tgz","fileCount":323,"unpackedSize":629802,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa2Y6yCRA9TVsSAnZWagAA1MoP/307SaoKkgDScfiLS8O4\nulgFXPDyswe+TQrrIYw7eD5zh0XcLAV1tfruMtPkHazQq5Pi9z9zaCgJphrd\neySVnx0/hlfXmIg4FJvl33/J8UFq3rf16Vb2zdDUGCb38RmnKlQFbEbqBq0X\nd5vb/CMsgXSPf4q8cO5jG3NmlvmFRyfBaERkE2NRUIKdya6i7NTAunEI5uhq\nJr3ztNcEROC6Bu1yBo5LWNKOXJrnY+v7IDkeKMociaw7K5IxsC5tqRGXj+qh\niORdsX1iVqwU468pqIXQY5U9fISPPePmQxe/oeTmU7Pu9w2b297m6iPdRLhs\nZF6WqhIpxLFGV4XDSNhiKYGpoWls0dCvc240tMtRsT5CU6PMSJYtyfjkvsSi\ndyVVCdKMKR8vyS8rX6+CVs/0aULOtLVHsiNFmPEt42aiaBjJCYYtO/bd918B\nUwKp6fZD6YH5QRHHbwrhKTmEbqMyeWlgtZyWbySxNLNG+/6IQPUFVqeioY/n\nmLx7lZSzBZ6z1NTkj+DwFh1newdzhzN7hOyLUQvctEp20/zsawUzfPzOynSI\noLb0PDY+5DElaivJ5VT0Q7cMGf7vHswTtNXWKTEx9r/gUCTqtnSvBLw8kwWl\n48dALBi60pE+SvnrTcJP7GE25ZAAGfc+515I7kBYaUoKbkVc1zQAkyXG9oVU\n8+LN\r\n=lqEy\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-wkdxSIOnuWcyGttXXFw7htKQ+v8eGPm1Mqje34GrlsFjxHB5V3NE5OCVyiyMOL+eGC0FtkFTXLsA3W7vq0P0Aw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC6KoAAuGMswpGbCdyorAdfEMvTd6G/o+6rEt1laVG5rQIgMqHXtiv5PG7BxXyGLHVbEpmMFh9dofZDLysIRDAwnKI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.4_1524207282456_0.8221492739267573"},"_hasShrinkwrap":false},"0.11.5":{"name":"teambition-sdk","version":"0.11.5","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.5","_shasum":"7be2637823be8646fa9ab95584816ecf361724df","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"7be2637823be8646fa9ab95584816ecf361724df","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.5.tgz","fileCount":323,"unpackedSize":632601,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa2Zc2CRA9TVsSAnZWagAAX0UP/jTEmAd/leESjsD16uCR\n0Ags2pRTeO+oeZ9YRFxeHKmrKeWaVIHNe3VddVjNFsTu9VjHY0kb9EZUK+Mz\nERWc74qb6w9I7+DUKLkpj7HGmCJTN0ZOtpjW99Fdb2SYnAJsXD4S82Hh3yIT\nQZB028V6TOqRX3ObvvjilHsK5nOtfn1qm1BGX/nlpR296qqxDPKpW0GEEUtG\nc0lukTo6f9gCNZBAN7V639udORUanCUbqHEUXwb/0TL0QFmHLs2N+R4PL45n\nhDPQvHoTz8vUuuDUponRX2D6Os3Z8ksNtVAweHS1zAcKWXXuOrCnEBjddjxF\nYoEHSP7qHLzPSzs4ZtCLgKq7xZFJtdnH3X1z0Hgv0lYn/cpfg+HLOZHWByGv\nwgqvl6vyhuNbQxwsYJLqBwUmvY7pAGxDc+oAKOILp+KkiJ/Fwg6AGOhtP5vy\npLT5NTevKIf74SbatUBAKokTkQZMm9RgMYKV+mbQcfO1utMm5x+hs833WJyb\nwCeMvvXD1gDQFV1EF2El84/LrFFet3HDFor8TD5jBbc2j7zxsGljg+r2ydW6\nqEbNevYWM5m/SijEsljT6elT2qtXbvKa+jIcYiRHOYvY236mxvSUjIumBDV0\nTGUlaALhoN5F6LGo4KEtG9V/nJvnQqkChjuBjjL9mDHangfXxgAMyZg/lgvd\n9vaX\r\n=eQPt\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-jWgQhpGh2aVdOMsz6AX6/1aCMoUH6+BjzbJKCQ9QjbXog/7SxLxdyFGGG9ekyEv2w35M8dhsCPJuL3uQTLj9hg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGreVRuhJK4lgxq309ye9cckdTkfoLAcK71WUnSgX0QgAiEAx+tCpdqCSGw7P6gL+DV0kNG/Ijv2E6O2TdqKcgM6B9w="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.5_1524209462671_0.830766146301543"},"_hasShrinkwrap":false},"0.6.15":{"name":"teambition-sdk","version":"0.6.15","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --isolatedModules --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.3","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2","isomorphic-fetch":"^2.2.1"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.4.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^2.0.0","tslib":"^1.7.1","tslint":"^4.3.1","typescript":"^2.3.4","whatwg-fetch":"^2.0.0"},"gitHead":"940d0e7dc9dbb4ed5fe4aa10d511baf9c5704b27","_id":"teambition-sdk@0.6.15","_shasum":"c13a27f510b9748be86cc31b676455552465df55","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"c13a27f510b9748be86cc31b676455552465df55","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.15.tgz","fileCount":1106,"unpackedSize":4282897,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa3b0gCRA9TVsSAnZWagAAjLoP/3fs+OYxsmzBR/14qpai\nvsxHRsZG/ZQNyIwF4CGopEv9vcj5hKRgkblLa9FtKWikGVt0BJRo/5DORkme\nwwyNMPSmoNQPVspISurnY86EAFh+X+QffvKP8ssW1ZyvNSApZjSAhPID3E1/\n6Aa7XdvuYjG8chFby+yzmUBzmGizhBPI+X9oQ+qveAwf9kxVIBpnkVm3oQr1\n8HXyv8x9PuQO3Ra6n/r5q/JucodZC+mnIHOiZKfRdGGkKmjXoX3XYfCumk0G\nbOpxiWp1YW9BOvYbKga5wp2Y9eF7+FMul4+QIndA+N2zb1IeC9EPBa17DgYx\nGdNybqsCp9LQz0N8s+Qlqf64KPc+ozlosSgESN+zwDVWXsGEnz/ol2yBlSxH\nDhywxd0PHdrnF/IxbHCY9TKxSeudxe92vAdG5lD/wvaEcHH2h9PY/IMuSIYa\ngNUnQWAqoEPAaD/9N15oe7F6gsJ2cu5UZpFAgBCA8pB2+uRM2ea0dAMlt9MD\novh7qJ0B5PmxjQYulwF8Uz4aVdpM+tCdJxOh1lWVIhBh0piCRWVSzdJRZyk/\nvE+8gsyLdCWc+BiV+UWP/ljE53w/8g9UptvePC5XN2fkJJ2tXLHSaUh+DVfk\nIRZMaMdJdh8TOT8HNh7usmySUI+YARX9vxu9zK74uPE7AkEAXpOPlR/LGH7+\nPkFg\r\n=OH0z\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-a024Yz5uha+n5H4vF4YxFjs5IDVgD76P+CZRCvr5PGDk+QojaED1BvqFiAhC4N7fP53fo1+tUKipQ5tfDMOKdQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC/K8qndaVa5jhjDKmARNXShC8PQGU3/kSIDi/v4TKegwIgTSAMEtz19CSNp2xudf4GsTgshf4KXmOywX8l1WeaXQs="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.15_1524481311910_0.5675627191501904"},"_hasShrinkwrap":false},"0.11.6":{"name":"teambition-sdk","version":"0.11.6","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.6","_shasum":"baba7b3787445bb7c80f1a5390f955b4d4db1592","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"baba7b3787445bb7c80f1a5390f955b4d4db1592","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.6.tgz","fileCount":323,"unpackedSize":632810,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa3wGXCRA9TVsSAnZWagAAtUoP/RvOs1B93AMJJtmX2TX/\nka3waqpkKi5HFYwjX5KaPatfbb0Iiqy4kHiFZ4Xl386107gqo/uYOVV9XHSU\nSW5qXOurOmPO8/JXaA1ISOQwnQdXA5VrbxW8m7y3psMNbNsNt9G0Bkzo7PsH\nCI5cCh3Ucd7IdACZM/e4s+m5AEcGGZKyffYtxta503yZrAzGei1izObk295T\nfNRFEm5E7ICJOv8qwQw0KlUDCX46vnQ1cRevE8LLVK8sbPMXxr8JS3MMoAmk\n0F6KFfmqthTg9NcMxk3CRGn3yy4BQJYhfOOb+rHcIcR0oTHzhwb6+1TAoKvA\nIvHplDJDNbIYEmQZIm27QlS3PHKaroHWQFw2L/f1VpsTGE1f40YWcaW6DiDq\n9EuD5diupGAWm8aoPo4mrd7NPpc9yQ6pq6ChARD3lqzl7PBdF7YVqFhBJdfE\nbaKPe/e6d+K9/X9NQE7ICMGSHzBc8JkSBqOs70RWTGV3yz7ZtG/ya+d2o1X8\n8TW9xjOfiZEQehtTT3DUmK1HU867w8tpkSfMMXsgCEpVS/FP0fApBfX0uuoQ\nR4qbg8dktKvuoaeKaY1CWjT77f04GqimO1rA80Medu0j6AMd33gtHOX2DCxK\nUoYlyYTgmWm6fadbwcAsBecSiKnMycyyWftqhpwPHtaMWBZNWkjquozI307o\n/j2m\r\n=tH0Q\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-QmhvVxzzueMs3Yn0ARTXZGn+38h9gEb1SdFEatVaDzvfP5Lm8xFebvfPhOrrmsXzbUwWhR41pjaiZHGlEH5X0g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDHqegTy6lwwdY604vAE+XnYnvkoZjnX4LPsb4nlsMSYAiEAlkXqD5o0XXf8qD34h/wXCr6ErDu3r0tFMUfBFAJ8MVk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.6_1524564375065_0.4387452442632547"},"_hasShrinkwrap":false},"0.6.17":{"name":"teambition-sdk","version":"0.6.17","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --isolatedModules --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"^5.0.3","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2","isomorphic-fetch":"^2.2.1"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^7.0.3","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"^5.4.0","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^2.0.0","tslib":"^1.7.1","tslint":"^4.3.1","typescript":"^2.3.4","whatwg-fetch":"^2.0.0"},"gitHead":"205a4456dcf926b5d5a29142369a4f9be38d91e8","_id":"teambition-sdk@0.6.17","_shasum":"3b31c38a88f128c3ceae4385bdeffdfc404d296a","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"3b31c38a88f128c3ceae4385bdeffdfc404d296a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.17.tgz","fileCount":1115,"unpackedSize":4332566,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa3/5ACRA9TVsSAnZWagAAEqoQAKR76Kt60YdZiK/unDDW\n8qGXUC07ya1eIxkBzdsrReMLLndNQQMZ1R4t0UZ1lRknNTYuaUV2YMW2MXQ+\nqHCKYdjV07T6Ctx/83QwkQeYXzCumXtcVDoUOALMLJ2SKobtPurE7o4BPMHt\nMPQokATKaMVaCfvk+tO6VJSe5gId7ja/h/ZRQvveQ51Q9/kty9YHiaMTCnAU\nOPXdNRuc1cLn3V3H+nw6mceRED+m1xgKkyIExFS/m4quIffmTsRvsbsbrq56\nZ0s4nv05woX/9GPlkDJXgN7coqxNkdaWMwHcB8QDWfZO5wd9JUAyzB5IWeLo\n6Xi4Mbg8pirlI6eTbC6Icve+4jK3PDUEzIEKMdgQpfVffzGppg9TdCGQ4knQ\nK/AKDIElYOMXRkPWIAB4hMdUv4NqFunRFCZRJlkXhlZ+nO6TmX5/GVktEQVk\nnV/Vel/ZYqrPXHT/Jw3jkG4o4Y4ki5HXkPB8WGj9FJhaNE5o6aO4NjwehV3a\nJebNa9xTR1ORI8kRTdNF0e5sbe/dutnYeav16POOFHkhHMgkBVUFugJyRLBY\nEj/xvgnpRmQ2vegIDtTg1k9yu6k0q9u9zgfy3Z3vbM1FzyBqHJlgEfLmpoeO\nYEh/fV87j/fPdVnj1HNBhzCjH6CCVTIYvDknRgUVTHm7uMwX/7txjPJUnt7A\n7bKG\r\n=yRY9\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-2kHKNFSa0Vla8OBLVWBmrx3wUUhsZDqlx75W0l21G9B2iVOaK7zzQMbM4k/g1fqpTPwGFuv5+zZHPNk1OGf9ZQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHBrb9Q061ZjMQYZJmoWfQGOsgl+B/+NQfMX06sJDU5CAiEA+h94x+M3fti8TT1TWJo1cOIPmf90G10fqu3TckzXy1c="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.17_1524629056015_0.5521873759394751"},"_hasShrinkwrap":false},"0.6.18":{"name":"teambition-sdk","version":"0.6.18","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"5","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^9.6.6","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"5","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^6.0.0","tslib":"^1.9.0","tslint":"^5.9.1","typescript":"^2.8.3","whatwg-fetch":"^2.0.0"},"gitHead":"ec3be65bb702e18d7a1b77dcaea9075d059c48fd","_id":"teambition-sdk@0.6.18","_shasum":"c426d10713fc8bc048b063605f44937a8a03cc62","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"c426d10713fc8bc048b063605f44937a8a03cc62","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.18.tgz","fileCount":1115,"unpackedSize":4359259,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4V0tCRA9TVsSAnZWagAAgg4P/j4xbkUj4FjlUNyRmXyX\nZgCiZzt/peQvH+w8PNqPKUNa6IVPXdM4uZTSnduBC0c9UO85E1+c1yOz3b9+\nTsXodduiOSuDt+z/JpVsWmzQFo0WVgCG2cAT2g6tR0wNN8LpzRyM+caOV7vR\n6m2Ya4dKgECtLt7wxayyi9Qd5Ozqz2vdtdwKvZgxhaIrxZdSHZ8mffXLJTyy\nzkF9LDrV1w26mPZNcOixKeiHeGv+qK7ER1bQyc0SEsmm2DLBuxJH1PejN204\nE+hQsMByUrukFMHkBcujksworI0NnB2nxh28O+ribvDHPQdm1K+x5iubdQ64\nEAMJ/kF+Dh4z2+tRY4CCwYCzMz71abYJSiJq8M/5UTdMl2aFr3nT+u1VTQ+C\nv8bXFsJpWJPI84KF0TPUQsRi41vfTirWmRAOaHcowu84S1KZuStKr+7rfilp\nkSLEiTyOMPgMpgIU8SbM1BAE0d2/yC7WzuKeQtaZZZnTbcXVq7eFHbBSWL74\nX9pTZCenW76uImQBhWjdIEEIdCQLzeFL5asIc2M91C0ugagHqQM2HBkMTI9g\n1qhYeh/3xyEP99iTIrkGEALNffr/lN1J7jJGlpqSqIDRcFomUsK1KPxwu46n\nM6B7ZrB6+zS+ypG4Jj5C5amD7GNyo4PLMN5vz8/sxSTCSOljD8gnOkAGXp/6\n/pr5\r\n=lsqV\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-Mdt1C5xxESxoWn+iZpUVyHGzJ73AFHYYV5b5m608Ucd9Outd24N2QVVpR67r1jUiwzki1z+5J7bFgn+2vfpJAQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCLa4nyHW0DRn/coh5W4KwRZhXujhOc07o7dD7L3ganLgIhANqineElt8PmWfrhf4dyCpC2+lrpMuu0UsG4mqYPXuC1"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.18_1524718893375_0.45177607648601836"},"_hasShrinkwrap":false},"0.6.20":{"name":"teambition-sdk","version":"0.6.20","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"5","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^9.6.6","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"5","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^6.0.0","tslib":"^1.9.0","tslint":"^5.9.1","typescript":"^2.8.3","whatwg-fetch":"^2.0.0"},"gitHead":"9310fb7bd0ff835d00f0d8961d63c4cd247c8d0c","_id":"teambition-sdk@0.6.20","_shasum":"8bf5832d454a5cb64b5899f3001fadcd53f36ae9","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"8bf5832d454a5cb64b5899f3001fadcd53f36ae9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.20.tgz","fileCount":1139,"unpackedSize":4388634,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4W3lCRA9TVsSAnZWagAAEQEQAJZBuUXuAgn42O7GV9II\n72e560wImZsHfNTu4pLy0WFt7jCSLCbUs7ugf2Q6XDihOmGNCVh+GwGH2KlW\n0NkRYZkikozeZb5O9Nf2HDamyJQ+hnzIgfV5xshjXIEMq0hY6U/aM5lUzeui\n+tx34Nr+merytxs4Br3i5tuFt1DpqWzXyZ78xQcinyqJX/MKRzoIbumNxH+9\nuvwXByPz2TOyHLsu/AvfdMEmOIB10vgCRb/4ykzUYCChQ2nx+J1UlLP2qzfz\nMAiu2TfkZOb0vBaplD4jKdkhMMDZhAqlBgNtLyfw0lheQ0l134LagKSLZVyJ\nv/yGugZHAvPLFzUbdVrM8GcayIL7mpUEOo+w+x/qOwE01yWo5QbnEKfqkduV\ngAGLH2EcGf+Xu5QQrvs3rA5aamkKEolhhXNgRwL23ZmG2t7QcU7eXgfK+DfY\nEoI22qtMFqtIVQhKOKXx0+qWoSxQw3FZ8cbrlWGD6VNe9AGC52x1tZv2keaa\nBV8fTeeJ95GVdVB9l3OL13ec+F8l4odSRKrVqaBpgbud7jIicZwaa4HD0E/4\nc3GMNtyZYoUGbPKiPHEZHcfwMtUDlvFWqLvsyBwpcok+kulpX0iqeE1jiaOK\n6SzVe+lY7fnoNaMkPzdlIP5+kMd9z6HKaS8JszhJWZBQeUyGC5aXKt8nalku\n6i6D\r\n=JNgt\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-qs/eKbppVPQHSqT+VQZKHbvh3mrSI1Sx/jCg4SvnOXHEeQhGiEQ0pkjBYEP6fa0Xf28WKFACLLjL2xxz6PWvdg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGctqYFfI95Nk8z+vsYCZvsKcvZw4fQo80yx8EeMfFb4AiEA0Q+2kj8cXU0a/cSRY+otakZxqnSRrUmTDVCa4tNXmwY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.20_1524723172680_0.6624487218793307"},"_hasShrinkwrap":false},"0.11.7":{"name":"teambition-sdk","version":"0.11.7","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.7","_shasum":"5245f502a7ee90113f76acfa3fa54c457868fcf2","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"5245f502a7ee90113f76acfa3fa54c457868fcf2","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.7.tgz","fileCount":323,"unpackedSize":633354,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4Xp+CRA9TVsSAnZWagAAlfUQAIa0ghi8Z+89QH3ch1Zf\nLCvLUHsxMs5uptUhXfaZZNAcZjgTGzzKnz3jMm1McEoVpF0yF0hUDlKkQhdA\n1JjXdoMIjmycDEWNQkO1vYKOtVZ+JOIVgDPcOHRupejQqiPJlKMRTKTgtkQH\n0b361PGsBrD2cJD/JVKIzC6hltV9qcojEsHe8C6uidxPsmGhL64kemo/EzE4\nqp2DASMvDGWwEipQwN0gLnYJr+iYWlBkwJgEMZn+V8Yt6wKHXdQOWe1MtLYI\nwMcZBl48q33j8o3Q0+Fe9w1bmqfE82zVq6i0AfQcbJbHiep4Pzldd/3GilYq\nm2H/o+V/583dnghYWYdjP0dsZrXnXNEU16kRXxUTVOBJon8VTRad8sl0hR/Q\ns8nBkOOxHnnyrItJwy+6sf8snKQCbdTnzhtDnvoUKr1TGXQZBx7GYhiYnnQR\nW+xpuTL69Icc0zg8nqYVKnHCbJR4s7bthGHAgmg2u52ECPwn2q5o02x/jOa3\n2/2Eyu2eJ3XqEU0gISqlsf2InfFQ0J9JBKfIbpAMV7o3cHiQ5zwsOA7+46Q4\nyE2Uw1yLj4KOYvmWRscWJm6XBof5daVLXyWwcMjdB0xmARF+Zbz4iQwYfi7T\ncziWR47hXSrVWKJUPVXrqOKu2h9BVdkp9NCnMOdPgzrcHUYUxPRujkV3XjxK\nsZT+\r\n=j7iQ\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-hGgaRok3k7/X7Ql3yxz09QyfmtBaU4rjI9zFckFfG/2IO1jlWMWrWSBBhXjVoiEeWMeLcd4BwuM01v0WTWyVnw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEzYbwYYJOhcolj3QIQ04Bbrnow85YLkE1SKgSoRCAaLAiBDlKg2DjqBB0zZeDbuffzOP2XMfBKEkW3QMlH4wMj+kw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.7_1524726398701_0.5752964566335281"},"_hasShrinkwrap":false},"0.6.21":{"name":"teambition-sdk","version":"0.6.21","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"5","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^9.6.6","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"5","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^6.0.0","tslib":"^1.9.0","tslint":"^5.9.1","typescript":"^2.8.3","whatwg-fetch":"^2.0.0"},"gitHead":"2f8ffe3824cdfc4aa5de3b4116bd1674635d987e","_id":"teambition-sdk@0.6.21","_shasum":"f047b1a3fba44a87a96ec112a7025e5ceda2c18b","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.14.1","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"f047b1a3fba44a87a96ec112a7025e5ceda2c18b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.21.tgz","fileCount":1217,"unpackedSize":4551899,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4p2YCRA9TVsSAnZWagAAQK0P/ipozKauBSw1vtYyS3Oz\nOgcCrLitxG7WRTr5Lq2h436diMKDOQKYqVsXpwG3XQq/gM+6zl1Lre+/DuRz\nWmse0xalhtFZwefmwYJDHOaL6PsGrYs73yWVARSHY/eQJqjw86dj903mO0n/\nQ2jpataKcx7r/VJuLmXNLHgED+U0qBeaMbjql39PooKbD/upufJDbOJqoa7v\njqXn6sNPswgsKKI3luSjTIfLsHTXnBt6SfvhNzK9vY8eymhjUP+yt93OtVK3\nkY0zaN1B5KcTg/DBp3H/uMbeExfFL1yjhlKVPiFl+yrAFJnQMs+xiwjwjMWq\nCCwYisQpbtYKSdOXgJerRee/8bCi2ZKEqF6cJUPLgi3zKNTpN/BTP5FdL5Pb\n8IoG2Bn1oB+3UE+Rd9E0uXht5pscpJp0jA1Vifbch51/ru2xrk6OBPKGhKef\nVyt3n7lH11KRYeoETP9kJdbRS9Gt89KL5zQokF8q0hM+0H/vy88p6cfqoQ+0\nBot/1AJHmZvRnn39TVwl3963X63F+XGOItMLz7lLKrnMOl26YKaWgnHdf1h+\ncaY7JOUAZGG+2bhHSEOS6AEaBo2EWm3s6bFvYSZvbIeEq7gO8ghAgD11zWd7\npRh8tlClOIOjmOPyTse2Vq13NBRLH8G7k4h4wELyGZZBOMCHSkabONnWFOLf\nz0dK\r\n=i8aQ\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-b9ruofBHdlTjYXPhUAQ6egM6IRibLlgUdZFTMYXp1QzVmghF0e3hKSLwNNvgiY6dPDOI8tmCMj/Ut8xCpkyf3Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDfGpNbvi3LLyFcWal0o8amK/JP2AfodbadS/ofs74B2AiEAqUmS+ZafG2/D3ZmexZI+Yi2Ci1/CgbVYEj/4Bcs5J+o="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.21_1524800920518_0.8371303264192853"},"_hasShrinkwrap":false},"0.12.0-alpha.0-wsmidware":{"name":"teambition-sdk","version":"0.12.0-alpha.0-wsmidware","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.3.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.12.0-alpha.0-wsmidware","_shasum":"cf3193aa89eefd9c7270ab4882a1a06cb79b1d29","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"cf3193aa89eefd9c7270ab4882a1a06cb79b1d29","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.0-alpha.0-wsmidware.tgz","fileCount":341,"unpackedSize":678818,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa6v5RCRA9TVsSAnZWagAA2goP/02wM+83ewTAbeuDtGkg\n3PAnXSPjwBBK8cydw6dpiJJDXw7e5Gijd6X4DhBmElMc9TIabEZs4fCS0elj\noCVR1hWVIym5paU5jUKZKhPMc5wlQbuSjbhT31ArgWEKYEksak2jEaIm7Cuj\nBMvW7coUY1SGiQH/M97zM/P5PpPk0jMwr0WdSN6ztZQ0bRdjVf3Tjk7M8Gck\n9wDtAIcbI1dIIx+T9Jw1MDM+pA8zYacVG34ggf4Tei7nMoc6cH9oG349LCbG\nmYdsokRcx8KLdZoad0PGbeUWsDU89EFIoe2wh5YwbbH2gHl9BEjsqnjf73z+\nLvCR4H5i57xU7yHxwTFwK2d7IiimbH8TZoBDRo8lvuPh9CjHRZEbnIXGuonF\nXSO2BRC5N5S9oZyeFnWWSPyRmFnAGtVvTSWLiyVJbM2UW8oSyyu57O2EmuRH\nQF5v7itk5xxGb6O+prByJHgFuFGBoCxip6IlHD4ICTBWWs+9IwEPVD7RS10n\n1/mi/zAh784h7x+CZyYER/FQmcXOpgC67sHShthpkFmEQHRR3OQdDCAUrB3R\n9pFb28/hOu7O2rpDFXqSiuA9yXcokJtSwUa+BzTtQxQ0Y0r+fOIhYMyikKk/\n/fNGGKl9i6fXsnAmD49/3BtjV0lBOAV2SgAOD7GJ3IIBgixdmUwyo+X8EFsf\nPoUa\r\n=xDeT\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-uqShS3OJIn3TGHtw1Kk9CzKIJuxsWT1ESwQSoetZNNT5gzp+g5FD9r6iBL11NF1WSVX+kcggyhKo2eA5pIwmkw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDOulK73BmwpzBd8z8WqOa4aT/RsYvrWG1hf17V2vIlMAIgawkXmSNqIQXpbtPJOajpxwJlijtwXtlp4YG+NuX45P0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.0-alpha.0-wsmidware_1525349969258_0.7436881627686911"},"_hasShrinkwrap":false},"0.6.22":{"name":"teambition-sdk","version":"0.6.22","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"5","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^9.6.6","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"5","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^6.0.0","tslib":"^1.9.0","tslint":"^5.9.1","typescript":"^2.8.3","whatwg-fetch":"^2.0.0"},"gitHead":"a3fb70e71fdfd36ba2c739266d9205a8d1c18d9d","_id":"teambition-sdk@0.6.22","_shasum":"11b6965015ec00a0f9cee4461679161143176abd","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.14.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"11b6965015ec00a0f9cee4461679161143176abd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.22.tgz","fileCount":1217,"unpackedSize":4553061,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa8XG6CRA9TVsSAnZWagAAHlsP+wYlayW4CRhr/BzKwlH7\nv3/HLhpOVgLmuO8HyaOsA+eT2QfY3Zoaq7woC68/QyRwVvsKhZfi5gFH+0NU\n/BajQUEKehmFImOX5To7ze7ZLka86npKasvBxe8dyYNzE2ri1F5Hgi7DyyOb\nNMri12tq5bZJ/rAhU1OfGMA2PCzgit1V6dZM33CNXvpCvSY3NQiHB9O5Poq5\n4TrVeFvqXkUwqhvCVKTHRyJlQEVUf1Po/l19LDgzVOWsrvG8zVWM1+/ECviU\n3f9SvVjMup+QHYDNkTJrnCODLRFzh1LNCmJRkkTrV/imJ8cx57a1KiD5IxG4\nZ26hVYEuAkSL6ogf94HjbFxbKCqCkOTwnwW+zHwTK+7y8X0InMaUcevSF0PQ\n3xg9JSKyEP6ILMzG/0xdmv/FcdcE0Iyteutj5BWqgecdbuVBZ38J2eY/Inqu\nZs96qnb5tZSt6DGM3ojoiv5lFAHDskjZJNdFHetxSASXER7n90Xyf23TDo0v\n9FDgR/3xtcRUZievxUd7heHkCnq7RGDccv/dC4C3/ww/m4jT8RXmkFGjWvm1\nBoJDL/Am5lWsaY/+txnhjMa7tQWIzmopcXw0naSmYKhgsNKgTIoLwoajXcCy\nx+S7+G2hrsk25trA3BUDQ5YsAeEmnKooDWCGBvfwhFr65xXZrqQXDu0RHyGq\ndb8a\r\n=KCuT\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-Fl4+nNe5r7L5nJCBt5z0KZaJ6eBrxjJaAUD3QXOUj4+BSSJLWYkEbyySNN9dj6vxzqEbXzUDY794rIeTlg4Qyg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH41Wh0AayF9qUX8P0AeuBTLCWEKgbhgOn2DrLFYAegnAiEAwDSrHJOc85ZrbydIzxijAvuUTIfOPsR0d+oRATBJHoM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.22_1525772730420_0.8977454171500967"},"_hasShrinkwrap":false},"0.11.8":{"name":"teambition-sdk","version":"0.11.8","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.8","_shasum":"c6256ad837d26b600c10577b97f2c88084b90a27","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"c6256ad837d26b600c10577b97f2c88084b90a27","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.8.tgz","fileCount":323,"unpackedSize":633565,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa8qiNCRA9TVsSAnZWagAALGAQAJ8vPurVujwI9xys4KOX\nD/25o7Ua4n+4k9gir5XgYi8D3Bdq5Ypb3WvkiW3gvoYI+lLPgYVYkFLwZgB7\n8jO1Kqq9C5dwosUjt1GEB7DCWwuOw6qf3rMqvBiEogb/cKPnktwyQCAhd5OM\n9cft1k25ZjeDiHVk7uEA5/AgaMCh3qMr4AGtdelFu0zlN7fYG609Ijv5RrTc\n0TCcCwhPv/gAYnzGPdP0trbENbWixh6ST2MRWi/bOd5B4iB5DOnwnoRrj9Sl\n9HaSNhCQEqEggGe++2HL7Y+wxRmENWLj/QHdp+sQ8hXX3S37ggIbFQxZBMqH\nJslNWUj+Sptuyqr8DJzpQKZ7Ui3qtHavOAd9MSOHbftY+J5AzLQAWfcGNaj0\n1uQgOZRGHbScG+vbBcwagvl+z2KQrHkMP3soj2OT9Vui9ifAicA7TrnK16YU\nQ+W83s6MyFD0p61N9VOclMaSW09jqNwbDf15XoIN32NgPdn8NXnpfIRNhFk6\ngA20wjgovvUHcKsXDoIZ40wI5cjELpYWcMKpssi7SO8fTPXhlr2Wv6sE1t27\n+cmgGGtnzuOkVldLxhhk4MJ0TFbRG2AJSIWkCkQMZF+Gag0dhq9vrjfcHA//\ntPhI4yo3TNhfAt6k4Zy+L8Ure1w3QYN/oS+aHiI+U4gUpxQO6FcFF0S51H30\nhyKD\r\n=6R8M\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-sqDhfum4+CvqD5xT27VEst9VwbnyVvytpYzGClemkNtnEnKqR334s0YjnhZuvQPMkSfVsVrX7PnqzmRlU+SHYg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICGIq2+LF/MfJxNzKHzkE4VyGwW38cIRtItksO4EpxejAiBoYk6W87bmEuwDC0N9fkj1QCr8aZk1AsTPhuvemplAGA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.8_1525852301663_0.6059649839325205"},"_hasShrinkwrap":false},"0.12.0":{"name":"teambition-sdk","version":"0.12.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.3.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.9.0","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.0","_shasum":"0aef3dd27ed544d7818fa5030b3331457c80a754","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"0aef3dd27ed544d7818fa5030b3331457c80a754","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.0.tgz","fileCount":341,"unpackedSize":674510,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa9WSlCRA9TVsSAnZWagAA3T4P/jT91E966WzUdZ+1zR3H\nUXfVfIYHXj/+2EzK1gxWdrzqwdXmciHw4aJAAy1qSzJArO5tjhsgxTP0/Aj1\nWl2L/uTuFq9430ThK47h6yI5IU7Bw70/m2ABA+HotGWENUy5nqzghSE7qM6R\n+vnc7GznKXSM57eXu4YNESBOTSy2Zk5ZBt/wmh1/qs43cY4m8j2OI3RuEvKC\n/uK7gSQVzdl+LmuuL2RLgti/XCAcczeC/mtVk1aKeIlb44PavcVbIiJmJrOb\nbFuGnyZYZtB0ffeLK2rPvEx/7WsKHuv8AP0PBUjU8ZF066yPYGSq/Z4V9+e5\nDHzQK5ZA5O0Rzc3XaADI6V3vD3uQ059BNYCNk4DVZpf6Vi3f5fZ6vpbRXXkM\ndzWBfPtQHBfyAVKLeV8I12+zjHxq8GGbYqvfR9Zc8dUosJGwRJgKF+8CFoC/\nxh/FDAp9cp8VGhKBAxTh1OvWqDPR1S9N4VdfKlaePIHQxX8rajIXZeHXJcqK\nhJzQkuNaCaAYQ+HHoVaMpVuQlhgvZmcKCEPPNtB7z9ZAwMYbFF9Ayvb4wOdW\nmpF+kWVr21AKWYAYjJ9/3QLJK6HAP6sHG7th76nZAjK+oG7bZMsWjOTjwKr1\nw6XwkSV2o4YFVqNuHq13CBwXC6SMgt7ElTpBRi8D4B6BdGEzCJOjc8F5+WJ/\nWv2d\r\n=Q9S1\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-9/J/pue1A5qoNkygoX319Nz6ZTA/ILGqjgK9tqLfI8QuwoRY1FTttJ43/YwcHUdL4OQy23zin8FfMvLt4vYo/g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDrANDjReslSmx8DRaR/UJhnQHAqIFAdsCjM0HocDpwgQIgOxS6m/LJqmlG8DiVnuM6QAdyPD/10v93C0zXkaLvJpM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.0_1526031525109_0.6562350173020266"},"_hasShrinkwrap":false},"0.11.9":{"name":"teambition-sdk","version":"0.11.9","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.9","_shasum":"a31f0bc3e8dbebdad974242feae08c2e25e26046","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"a31f0bc3e8dbebdad974242feae08c2e25e26046","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.9.tgz","fileCount":323,"unpackedSize":635464,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbB7B0CRA9TVsSAnZWagAAU40QAINkxFuWvjzXkbxEZa3t\n1ZaQK+YdMWdLK5n4txwwM7GmIw6dHLYDaq3UrtcfZzK5J8+EwNho9CrNIlMw\nETM3fZIN2MXU5Kbsu92nqhrIfThCAXG+4eaYa+IS5Td9COFCXGDRd/Pz3sF1\nOXHShEOYe33h2PX9W+M226RkjYdCjegrVxpthNYfLkiQX9pX4CaLLRvg9QcX\nqta1TMyyaGsZEgEqwoXdp/mES8KrTegRo7Kjfr6EKh4TQWIU1bAcyScnblUp\nc01Fc1aPIBTXCTWo2h3ThrH81ENtav9W8RuD2zJHYMPrs1VP3C5fH3dTpfPd\nn3vBs/zX8ooFQC0BXIjInvkQhzVPWacaKQOUAvVR+vurJTGB2ylRM8SBltEG\nkheGfIVczod3M1QZPV4vtB4Bft6bFNzJJUndR1Qso/OYQ/o1ZejS61PClO/N\nzx+azhYq77pAx9CIVmhClHEnCZLM4UK9Wx3nGp71pleY90RkfV4xAvvGeQMZ\nVWncgpbGdjic96mZ7NnKvUeThFZYa+y7yXGhIxFrelXyQZ0hfABHf91juoZa\n3imQTbCMS1l/78rbWP622qqSIqzbQbvZBB3GrRlYTJ1Y5wAKJRsX25J04yst\ngKz0YgULA85NXcT8StcGBysHzTxNnqR5ZOvYn4lAo2EsB5uia/tQXaKRy8l4\nWwG5\r\n=nn0K\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-rZSDHBUfCnj2jn2IZz2tMeAWrsejjIJ6+PZ5Xl1fwqRT/0PrHGoAemGruhO9EXtWMdGFZUVA+kexHZDl6Kghbg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF6gKmqgKa05x58MT/6pUz4WywfdL7u3mES54usXzgkoAiBrR6KLIiOKEt6shdGTGy7DHiw3iR2sOlRTgMCUpTFBlQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.9_1527230579845_0.1681544419547638"},"_hasShrinkwrap":false},"0.11.10":{"name":"teambition-sdk","version":"0.11.10","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.10","_shasum":"0ee6c2c264058849f2bc69a4b757396edb5a1ed0","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"0ee6c2c264058849f2bc69a4b757396edb5a1ed0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.10.tgz","fileCount":323,"unpackedSize":635405,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbB9IFCRA9TVsSAnZWagAAmToP/jWYIJqGsAL6296wi7FP\nxwWdzkUYMHeSt0A46PB+f+ffJEpXsZDYm9pRAGAw5HNybEDPWXoItPWTBxFT\ngm3DSAODcA8IdtWd8dszSHr7N1p04dpc1tPFZtZ2hn9gMJY8gu5yEWadS81U\nHsHfpoPl9QiojWuDyQfMYYRrcwq3Crp8xirJTT3Qt7CMuPV5U+qn4AseRfVQ\nt0qPy+Nl6V+8Qv3ceYOsbuf4Onn1+baKxQo7SH5dHtoofMCdiLK3Zb5qjCYZ\n0oOTv0Q0dobyDmBkW+zTm7mmOxGP/zrDxi2Cog2qg04lFTTs0cMAEez4GuoW\n7JnTT4OBMiQoBXSqkA1u0IXmo2veIZGaguLvQsP6ZVEdxdE/oBWUmKDZUHPI\nMVlEoYkLGagkxk4NI+bPoTdQa6vwVtWiBIkvP3CjGnM3eWzaTsfU8QyvPkj8\nA8ZqHlAx4hQ+7LIqhh/Zf7k6yExJnnTi9bNhexQdCwnTuV19jnY1QOSEzoAZ\nSNp+vJYCBYWm96pteDgO/+YpSDJ1D1OArZPOI+WIwoHRYtbKCK2dRK8slcVC\nj3JgQLWC7Gt1pVPwM64rJAuuauKvNft3Gp+pVt7kGTdhOdtWkZpNl6LFaZj7\nXHE20MIccFO/lUn+y9dH283jVZstM20WpOHh+f4oBY2LwNUdH7xUhOhSkMku\nH3sI\r\n=SReS\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-MbsFOr7TNi1cUU2z3n9THe/vcRu/75o+78LgLphjHweJBO1Rq7R/fmFo7MV5/SJgvzWuFNpIx7utP0LdZJs3mg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAiVqR0zj5FFjoId136tagSfjYmSSsYp05xtCR36Y1nrAiBDaxuFju79NVe2Npv2Lz6R/r71YFvL82ZU/YcaPQbJfw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.10_1527239173074_0.224837139848302"},"_hasShrinkwrap":false},"0.11.11-alpha.1-cfc":{"name":"teambition-sdk","version":"0.11.11-alpha.1-cfc","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.11-alpha.1-cfc","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-9gTzHposLwhAuFFhXfjoyxcBMFeFYPPfQDPjKK1g2hlH0mG5HjpczxTro47s12XPYnIXSFkvHQnn9uaLmLhQ6A==","shasum":"f99a5a394854e67bb7742f27137a6eff602ebf36","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.11-alpha.1-cfc.tgz","fileCount":326,"unpackedSize":639135,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbC+ciCRA9TVsSAnZWagAA6AsP/3ivU8NSX3VUyDyR4xGS\nyIVcUkFeg4mUt/xnw4Bv3JVMrj7YrSyR7BEp67I9hjSOMjjt7RydmoZXitev\nyGXLQq37VYmOZ4UWT4XnT4U6BvMfWeqnHI+o5ybt4XaU62kM3F9WJSLMhsJo\nmWMVSjwefLN95MfqguP3Txux8w/lUg6DgZN9UaNHfkoGzmYKc6ofw2RV8dQp\nAldRmKtPIdMujZb+M9Q8IWOUVgBIWtXnuArVppamX3UIYPA4N+8v/3ee7OJs\n/mqN2hei/n0aRtvE96sLiNeJXaMJ8WuxYIRzQpA53aelkpvz3JFK/yxsmbCx\nxdKJFf7In/0B50n9teoWypHNdsI1x1hfUKlnvWIDGDwDO7dbiT7Sxj8pqgqF\npLYY8mdIEwUqrgt1hLDLrLOCOGPdEhqC5RnCy4EQJNcKL5azV5Ht6bNV9P1G\nbwFkb1bsvudSCFaqVRxclnNq4jopTtpnYU81D3RKqRd5N3hKhkrP2kTiqDPL\nCzHjshyFMXjyR2ZZ7+wPgGM0Zh38UhDWbaWjGqKtghjC2I0qu9fC3oj1QnEy\nQBucFVm4bOakRnIK9vaZtXpqs7HLTD0FjGZHorBUGUm4LLwz4hh2dRorah/v\ndxcHtxn8xSGdjmuTDYssngFCIJaJNDz5rpXxFONqkIMcCpycATGAyKxGKChE\nvV3Y\r\n=BkMW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICUlxXSprpHoyCF6Pnzgm+jOrjoWsev1D2zEK7l7cuCMAiBnB/r0Of338Zky+oWpsRYTuQf3MLKtYy8/MRrPN+gemA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.11-alpha.1-cfc_1527506722353_0.7174631490986696"},"_hasShrinkwrap":false},"0.11.11-alpha.2-cfl":{"name":"teambition-sdk","version":"0.11.11-alpha.2-cfl","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.11-alpha.2-cfl","_npmVersion":"6.1.0","_nodeVersion":"8.11.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-k1nBc7v25by4mz7uRROQX+yTXmP7fdCQUT498G5osAJFP2kw1kFAXBBIX6E/LWGCWzsgJC/F5BIkDb8DfrbzdA==","shasum":"31a233eb170ef3cdde7d23ea6313a745ef1c7dba","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.11-alpha.2-cfl.tgz","fileCount":326,"unpackedSize":639414,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbENsiCRA9TVsSAnZWagAAyKQP+QEunctG/qIMX/I8Soqb\niWORBsmNK6POtuQwTz65n034bWgXI5zAP0rFjsZnFX799pyhXQ45n8louVBZ\n+flpaW20N2PSO7Ez2HgC45oQlFMUgYdmPYAjmWhL/9EL48HtMgc1VXfkCNIL\nW/mEYZc00ob0sAZebAy9JF906E++QmcAB0ay269nt0pORsAlM1ZWlfyfRDTr\noINp9UlsrkPM/QOnAzM2k7ESXuPRhwtCCifX1GQI2gEkpWWhqRlss6P0AniA\nGE6jMUuYldIzmP/7sRCekSOYbMlrzxRc3I8JIN3Zv5GGS2qxHWYcwfOrPygD\nxuir7/1QKp1GWz6QT0aZ0GpFEIPJddrgHulNJ4dhaNYG+I3ux4TeKTCxOSCJ\nnVbHbqHvAa6JJsPp5+O+845bATWRGqlaK+ol9G/VSiYFzM2xsSEgISSpGvWx\nGl1EMs/HE+Jd02amAdsGrx4hrbdZ4sqLeZ6eGOOK7KwEnN9kyn1xvn/hSKKW\n0FHv5neN3EgEDFsIpeXxM13NbaiN8Yee8PLf0XD6AUPmAg+Y17POWLJ5Feqd\nOT1tiFd6BOvYEhGJYkCqDW1qY0dP6WWC1lAA4n2mzNIy0XXd2k5d+dRKfcGi\ncFp3ur6ASA59i2QRUDtzo2Gtix1IPEVCby9N5dTiNaVzL0JwVM0UN2iPj6jV\nIeez\r\n=IqGr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE802WWZ+BRi7/JieWhq/mrxxYdruDhHI5BkOgCtDUQGAiEAz3/qqNSkepNZnEnseZk9TE72tVKpLjUkrzXwWOJryiA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.11-alpha.2-cfl_1527831330063_0.9894335869399975"},"_hasShrinkwrap":false},"0.11.11-alpha.3-cfl":{"name":"teambition-sdk","version":"0.11.11-alpha.3-cfl","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.11-alpha.3-cfl","_npmVersion":"6.1.0","_nodeVersion":"8.11.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-cZwXhJQCIsMKmYjpzRgyze6WIUfIkLsFBLYMThOsLqSR7JkGnV6WrwxcBlQ5faD5zrR9NFqv0sbrhnyiZIxr4A==","shasum":"9a34695dd0e81e156cbc73186f2537362e950f85","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.11-alpha.3-cfl.tgz","fileCount":326,"unpackedSize":639743,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbF3dNCRA9TVsSAnZWagAAsL8P/Ao1cZRun8kcJcs+IQyM\nCI90ioDmu3EI7mKVXRy4bGPlO1bBPNuN/YxJkFdVqG1i2azbMDl8AWk5XiGf\n2q9Pn3fHEQKsbfKxwvApuQOv2JxKSE1MMh4erFcpI0m4qM1i09T0EGM1KqK0\nyGyheQi0YNiRzUDaD+Z8rhBMuMPoRIo9XrSykN3Q0chcdNtiA0EaP4wlN6w4\nKekbvXcO84alqQCyyOG7l7+Go5ur5N6gzoMc+4WFgvQkFyD/YCnb79iPnwq0\nYZ0umlFADczH54+rihBW+43zA0B97dBbXCFLMGLdzFEFBOFj+pVEyCYlaMod\nzQ5rFKZoQIV4wIQ/bRny0Gb487KXQ14xobuDApGHQJNWvPAWSzyfzXiR+nA6\nX89eatsqeynlGawDTQFVUe/5rV09HvUQnC0QRK19qvNijJqFU2ZuJ8CoGGrb\nx4uLpShhvSf7OHXnivOkCW4kTGfndsunGexTG1fjgmW7y6hCceM2sScly72+\nUxba6l7OMseAIWT7dlCaulzovhujEdFR78xTfS+cnmJr/ET1aM+eSXEoTO10\nQiBH2+ktKVa7XeUY97uRHtaZWHAKhQuigEXU685gRiMBp94tq37pyNqhrqHg\noozAAMLnIdSGrMAl0O0bcaYW1T8VFDuaHrxukOzjiFXFQj2UVBLFxqM163cw\nLd5q\r\n=Zbvl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAnfw+1rzLGwGZ0BYX4v/HvHm3yhu1HN5ozRb52FldCvAiEAqaLZri5bdUwrm7s87rpet2Aar2RIJVPun3Zj3hShLRk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.11-alpha.3-cfl_1528264525011_0.0870049730237934"},"_hasShrinkwrap":false},"0.11.12-alpha.0-dbcard":{"name":"teambition-sdk","version":"0.11.12-alpha.0-dbcard","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.12-alpha.0-dbcard","_npmVersion":"6.1.0","_nodeVersion":"8.11.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-NMhbIfsPaxTSTZc1MR/jwxo2hVdGLWtsc5YXpWJsO4woN4glA+JUnUzpVhVlPZKaGZon+pW5olvNB0QpfAufaA==","shasum":"c46e668930f2647861ee479da48f38409e97ec1d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.12-alpha.0-dbcard.tgz","fileCount":326,"unpackedSize":639687,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbF5Q+CRA9TVsSAnZWagAAduMP/RUwy6ycLlhsE1+OEbio\nO9XLRSPm4K246X5hRR6n0TRYrbOikudCvFjrYC3cN0VZezuDgZwRcG5COXP1\nH4IqrsIeSTkT6XzyI5duSpFl84Pc4Nu35nyKT0ls+BumNSiHOK2qQt4JCV3o\nb3REg0TI4ucROLyIqzyxi8g9LIaoOzyQ3wk12rM+uLPmg/Z+XS11Iw23nto/\nBr4bphwIUzBMEJG0cCE9sRjxdIjcUMTW3KVDNqk2gnORM71fzgyJr5cuIWzU\nuTY/e5dlHHsIrGfVmxSXXVp4VK7MAvBPe4qV83vd3dIHqEgqDMfgfBKzFDu0\nGfh63U4nTZhuTPr0XR/71hQZXhPpCgK5+Mw3sv1/s2O+vjdrUmNDPabUo2Z4\nZ4PYIfbsh9c9OCenEHilmX6ufyX23uQbKWNkxPoJhURkHTKxCG+sDnPj0YcW\na13rWvUxPPgUD+GeWqH0B+XZEa1hRujT/xZ5ropvxg3yGkU2BQTXvMkaaeQZ\n/ejSzTvUJAaIl044N4l20F9xptxPV6wuQFnGZ5oQh9Bx+iA2whDfLWjv65SF\nV1PQOOmVvlNG6TEo55HVnftYJ2HctCNPGuLxYfDgmKXBxTkTomqieFzuwPTa\nWu7gL76IJjSbdmZlnnsjeyhzgTpj8mq9rUs5mNRrmTp7jLAGSK4Jy/4cPvgk\nIy4i\r\n=0YfW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA5eXbOrFFQbQofVcQkJRym/chl2Kj2koFqII8KZD8l7AiAtezNTIbidMYtVMLZc+32YZhOaGEXMtYgaFWKWmwIjjw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.12-alpha.0-dbcard_1528271933534_0.5756552093613294"},"_hasShrinkwrap":false},"0.11.11":{"name":"teambition-sdk","version":"0.11.11","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.11","_npmVersion":"6.1.0","_nodeVersion":"8.11.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-AKDK/2Y6WwppopW3aPBjZwKYgbtzlJy85RWQqlADOV7X7cO+bmRdD9ArLMcQxVqU2iVdTCvyxhEL4B2+PCGYlw==","shasum":"e22f2acdb5b6429b6f34c86ba002f3c6eaf37e93","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.11.tgz","fileCount":326,"unpackedSize":639731,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbF5fNCRA9TVsSAnZWagAAZ2gP/3AWHkfPS4leeFT87XOd\nZUED/o6o1MG/Gpp7iJwkIClBwI/HWVkR4iD8S39IcyBQQcr2OOcAQA3jkcqK\ntsh7e5khlYGmRFVDsfAApD6STR8461lRW7PdZXxJy46nsb0DVf5U9L4hhRw2\nZ7wkTx6t3fnCK9DmodavE2grZz8VVF+Sgky6RqJhgvcMDZvRthFdSOFOwSwF\nhzwUB5rZmQv/gQF9RondyH4zPL5wnajJWxsMmrsw8JKjqTRjehYioXE8NK9L\nvrGqZaL1RLvLT0hsdp987xu0Gan/k/4Ocy+/ZADJwzFaXsWtQdnCRT18grbK\nLYfbEyZ02Nz3FcbO4DsijcumPkgjz9489Glik3aEmLRgT1Czu5syXxfuusJn\nBRbONA7ZlkzPOr1w4hsS0moyfWcBtXnV76l58qovsAHCxZzzqL0Nl6QYNGM9\neBYQ/ASbZYVmtQUUF9WoU+alL8BJJ8GGSmbnYNdPFrLfrWtAkrkDDoRxo+Kl\nCmDgBnJbzkKMO4R6Dl8xUvE+G1f0jVxJupmy59aywFymAOWHVj5rpZR64CSs\nsjHwkCSjn8GqoTQG4POkz3D3yhZK8RohulocCfHMz04gTtEYqIvYwoImh90f\n9eE67nWIfqXt2mjKR/Qw3hGdQDg9h3JDbCyKtIC5C9S2by7M3y+/YTDHsB7O\nJVGp\r\n=NGdd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDynlwetpMajkXC3rg5kYHRG/IQw5oFM3yi4hbPusQdUAiEAndbZfQsqJ8/uwd/2of1+PVPVxoBhB98Fidke95GsjnE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.11_1528272844986_0.5400831752711273"},"_hasShrinkwrap":false},"0.11.12-alpha.1-dbcard":{"name":"teambition-sdk","version":"0.11.12-alpha.1-dbcard","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.58.2","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.11.12-alpha.1-dbcard","_npmVersion":"5.6.0","_nodeVersion":"8.5.0","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-FsCYLWkmWECC8gYtdHWjA7iMchoxda6YS4LCP4U7oopyUtzf0AjQvvw2xJ03CtqnuTN0zIe5UuAA2oikBXb+/w==","shasum":"a94ff884cebf4133996c6b07577096a4ed28264f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.12-alpha.1-dbcard.tgz","fileCount":344,"unpackedSize":681286,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbGnnvCRA9TVsSAnZWagAAG5YP/3Q3ZpecBDwnyFs4ijqH\nTjmmhfSmyFNqLIdajhHI1QXLCQHirdiqGkbcUscUSGTyQNSZb1Yq1XoY2U1j\nHikWsRM94x7yHW3RajnUIoJaWC6NsnBlFwAaDZB/ibqknuXV4CvbZ2kuWE9z\nORCzjRNatMH5rUJ06Hr+50KOFqIGwU6QlY2TJgvP73hqSeXlraGcMaaiMm2b\ndzG4hHJBRAAM5tnp2z+UFQjDCo/bkg4XubTdPicSlwVg3ReFFm66MRwdzcNh\n1gyM/rwqzvQdqHw7nxITQeVT364cti9idl1IrE9haScf71GG9gRftE1M10Ib\niQlnvON9DwCRreoY3aK97KJeAk+pyWcy9rZSZfAqBzmegejWOqo+8xA3ope4\nzB1WUDgRjrjsJpel/zkSJsj5q2M8gkWCTeMWOd6Y/TP2sgrmwWWMdHnv41zR\nHpZftWj686JUFOahVtZugOKwkkAHhjrurZvznFMgZ40Y+aWtMNKTuOP5hieY\nd4LP5wSSZdpiZUt0RngERSklKeGH45f6Gw5LkBP5JdSFHCvPVeitAuhG7mo1\nUcpsubxP/aRLunPTfT0B49Qx3YryLWus/OtCcflkwBPBBrfAxWPwwby5Jt6w\ngEuJs0OupnG1qOzj4E6dz+mrO8tKgp6p0z9EKK4+maXOEv7xAp44VPCHc4C+\nJqYg\r\n=G8r9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICK2n/NKSnVcGkfdcuFuLkLnkSUPnFY/xNQRS7eLQSZGAiAfReB1Wl7/Rxyv5dW5DGSE3Iz82lOGBTkZyb92AB/HGA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.12-alpha.1-dbcard_1528461806888_0.73998298533331"},"_hasShrinkwrap":false},"0.12.2":{"name":"teambition-sdk","version":"0.12.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.58.2","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.2","_npmVersion":"6.1.0","_nodeVersion":"8.11.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-E2bKR7y3O4ku6ObHF2JUQCjLLJNfuP49G2FdwjnljtXEQRvGH2gXSugMgddYaLf0DO59H+5mWRj3NHRO1hsdHw==","shasum":"8e9e77284f27fb340e05c65edb0bddd5e145ec52","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.2.tgz","fileCount":344,"unpackedSize":680734,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbHOPiCRA9TVsSAnZWagAAnkMQAKLeO+qkzCifINbq5DWP\n+cW6Ku27P19zdJpbnRuLPH98sLacLCxjdwYV/x1QkC54fOksddlK93Oz7BtM\nFAH4FBtOO12iV3oIiNFl6sCm8aru+XhnTxAq3W3lY7RnWAiUMz7Bnh/EKQXZ\nQmIx56O349iZa80HuyVykJ/+/ZT6lcPFa2dGJQHecVzsnkQd+6z2ZZWM2aSs\nZQlZoYBYfmeWDeLqxm8IvA6WSVJ26MpjaKf/6aYW8IddrYA++OLzTaK4NAwj\nTm9QF2mjKiZh9XWePNCsCMX52x7+qWMgMS6GISQKNPCr/klJ5cIn9IHUnUYZ\nuG964bgtpV/WC1tIQRFL3Gy3nXW1IeDeiP3JJzGdibLd9u3RuKJ5360NPtUB\nhLKhqVuxsdkM7y/VWjH/o+lKeoB8CdRgv26vu0+WPPwdZ3PCO6d3mmD77XaN\nBt2DBAro5yPui9GxeG0f/BxSVR6+ks9JEXkZghx9TU5t/QlvGTgN54cGDgEb\n7lWPh+Ux2xDCVgJ3h7jm9ot2RG0uQpPrA4podKi1m8+48SG2WWKCjogDacbo\nJh6K/jpW9qal9BqYGVLrNXNGZgvxX5Mfdfb1Xak60NoxUdGW4jTpELyPH6sV\nytjlQic7W4O8sj+PvhLGKu8RQ71qV9FqpO2KN+ATxZX44DhrTapRn4hzYlv6\nMMjg\r\n=N4Mj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHJ4E0c4uiFcG2PA/MWMq5MzCxgIE2PAMhGjI3/XtXMXAiEA/1HRqFl2uCXqyPP9yFJybArz//uNs7Q+qSP6l72HRxc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.2_1528620002341_0.3510064593686779"},"_hasShrinkwrap":false},"0.12.3":{"name":"teambition-sdk","version":"0.12.3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.58.2","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.3","_npmVersion":"6.1.0","_nodeVersion":"8.11.2","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-5NIMZApqt7B2l/RoDtJfaqo5/vUBk8+ocHoxTI5STSz77p1dxJX4ZecirMOJp5wMaDl2BSk5Z5JdcAnYNZ2nsQ==","shasum":"e92eb9792aade86018704fabac3d5705168e1a5e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.3.tgz","fileCount":344,"unpackedSize":680674,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbHOhGCRA9TVsSAnZWagAAx3gQAJn/m5bv/KjNZjhkmCzd\nYSUYx4kLvSSg3gn3J3litjPV3uXdTZNInmwntoltIuBshO90US/mpWZskNc+\nZNU9Y2oyBfDiFYLDrE2f6rEvPQyonQ/Xwq0qvsm5eicBjbPW1gD95sjvty16\nnPciBeU/PQv/jxcUwvEJZS8qZLC58lzjVPMQUyjqb24l7559DjfOtqagFGAi\nzOvSr/7cDApvMB88trmtthC96JQBinFvsjnYNnCWkKC7hMunjpO8BB2T//wk\nYEID8JqLxpoN+quGLXQigcL/vfF3aLmUVoduyKlvt5IegFW6KnMkHpLGkSGP\nhqm5XbIubzNikyNxW4itNtptXppk+kxrQnBJFdB1/bVOUw/4R3FT+WzEgbUj\nBA2URRb9endso1mvaSKPGzgN8uwpnRX/IRsbUtJVvmqXNM4nP6aPVoqEL2/S\nwPXRGAuyoAMORnjRlm+PUIBMeqDUWYeZPPfpaWMKWuiozBM4v0S3HzeJd6wd\n9Usnkb/7V/OipE1+7I5wYkhUrJBVSyPEtOw5fZ+M1h4Yfm5myyRwVlqA8lbD\nAeh6M1RDJY9vCGl8+EPcyKlkST+C+jCiv8sZaRyH1KVaHK1mbuXGoK7hz7Fz\npVeQLSBc6q+ui6N7/ALQ3DOgySO2ryoVBXsuZcdIMwOHvMw5427flrdjEOZY\nkIZr\r\n=NPYg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB18+yO2UxQlghMg2Me0in8TMvxFYbPWUFtWICF8SZs5AiEA6vwHDjrzn1ZR94edxhfndIax1UI/xVbS+UfvcA8zzM4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.3_1528621125837_0.7068404456368842"},"_hasShrinkwrap":false},"0.11.12-alpha.2-acf":{"name":"teambition-sdk","version":"0.11.12-alpha.2-acf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.12-alpha.2-acf","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-8g6n+qmv1xWJ3TFcCiVhG3n88QcuxkWmI2BLmmCUOwb2wG7F3d45cW7tUd/Q2rW3ST91BcNijPojGfeMvl8Twg==","shasum":"988a7dd093bee88fd83f6dc16f9ed3816c175662","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.12-alpha.2-acf.tgz","fileCount":326,"unpackedSize":642168,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbIgPsCRA9TVsSAnZWagAA8QEP/RLMBF8bejtF9CJpUdSy\nzICUB2gJITH1qW5AcQLNXLsOzV0KhhnFNFL/mxl3Pohyq6j53oz4u94nlXuP\nFLvKrJPva8QwzoiISyfNCU5Hv9rQuEz9P1L5i3C1DnUZqJNdBX8h19Kw+O2Y\nJocetuBZgxopFCYM3cAGcZ3h0DC2dH7z/JjyGT0vTd88SfG0Mwu4AyziI7Mt\nWsMd643+opWDIIOeLX0V61oQAv7h0+3iOnvOFDBDlQBY7MOX2NzcR04FsO8d\n1lKH0JXBbdH0O/fCYeSWC3yXqep869oh6D2ML0gOVcPWWIYsNefRcLBaTM25\nCjO48wf7AWr4LTbv5xfH4tlznBGeLoShSToas3CUw801logkL3GTR6K2Py+g\n9gDGSHQkRjYPGeaNg20LXaQUk3LD46mXnCAq+J5hdfFbpv31dec/VHmKyxls\nzx2wHlVd/XwZ+5R080GZVS8owD7HV5TArV3Go5YAt0wWcCs1D0WjzqiGFN6f\n+k2CQdoyHEVUUM8tASof8Kf/q/DZZrUx7tB/FEJftyuIqBlQlmi11E9nsreX\nC4yfXx2oFxL5UQ1I45q21/PnFsyz0Z4V/qmvXkX75eoCby/hmC9YSRIw5+iY\ni3ufgjPoln7D/bL82iAf1KcwSrPdykvpYg0hYhphG1ZE3DRuLJmXfLDEH2UM\nzAC2\r\n=OkaJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC57m8MJ4EPr7FK17pWWqGGWV8jizJCPpuA1V7DLux5NAIgAbPNutAioNbI3fd6+OyX/ojzeaoprElNhqMBGAx+6Dg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.12-alpha.2-acf_1528955883984_0.3532824470034879"},"_hasShrinkwrap":false},"0.12.4-alpha.0-dbcard-wsproxy":{"name":"teambition-sdk","version":"0.12.4-alpha.0-dbcard-wsproxy","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.4-alpha.0-dbcard-wsproxy","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-0RAsUGoZF54KM/1QkpGZPWTuu0rIN3gG6ISzdtO+FFB7L4KKh7tkW7M9BCQbI6rFNNoCqqGY9Gxm7s9nzP63Fg==","shasum":"236c2da2dc3e30c1db1a2896431bb41e4312658e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.4-alpha.0-dbcard-wsproxy.tgz","fileCount":350,"unpackedSize":687230,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbI0uWCRA9TVsSAnZWagAAi24P/1s0d47vweeiPea1tA0F\ndzGGyUhRGB2LgMJcRPJ6/4vCBUy4KhRFB8/Dt4R5jy0wlAlf9cblRnC5Ta50\n5Vnsc13nX+clFViPMmCmOYLL7n1RjDfGl55JzzXQIhaNN8P3GTY/D6GIuS5+\nlwn/xQHlFZdPbxTvWHCxMNbsNW5Mq+MwcbpC9oQeJVnXl+bVC1quIyDceonO\nwodjrcz/TXAPz6hF3VaQbU5iUHxPXhclUo7BaS0LXGgFAK95Z1xtGYq8P+gl\njeysQsSM7RF65xn1SC0WhHPOT8KcVcPAEIQ1RGD8lEleFTZfEFQ3UdZgtGKc\nHRhVpEsL0PeeOaauP6Z8ddQRPOobRmvkzAyxpUZZywZH0WJbwrmLNOK+j5bs\n3bQwfo0UOb20LdY+oGm77FuvRlrfEt+6elbdW5ERCtqZEbs208a9MftkiFYW\not0+ivJoTFryTqudpk+vXOutrWOCxxLac82i/cXS1N4QaDMg+CTpayE1qM2y\nVzgXM2Z4d45svuJB4fLDU6cvcBb7LA4/q3R9vfG72aMcOi3FH/9PHLcscxc+\n+778ZN6M5nxy6KVuFchC81WlmDsue/ql1HuXPMx2oQNFNb78QDpIDVB+2iMD\nRyAnN5jdh7HTwyaEvAc07D7r7XSVBSS8YH1tsVduaQltKBBCpsEaRqxMAkGK\nuLKk\r\n=2DS+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDbmk2E8drMf3UGm6rWwEtEDAjrp/ZG36uDx4trrZvZaAiEAh48CBhNXunyC5mcsRgYWOoT7TaISxIRh4MBIRTuL3Sc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.4-alpha.0-dbcard-wsproxy_1529039766704_0.4312008238662841"},"_hasShrinkwrap":false},"0.11.12-alpha.3-acf":{"name":"teambition-sdk","version":"0.11.12-alpha.3-acf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.12-alpha.3-acf","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-QcfAclHPJYkPmhAisQcPgKy7Zj116iT0iKQPZPTpq/3t/FMhMeo9ypGuU4YRH3hh0fcF4L2XDQn9uCyp7qgfNg==","shasum":"80ebaeb8e4108eb1a3289b49983510c21b9b83e4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.12-alpha.3-acf.tgz","fileCount":326,"unpackedSize":642226,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbKc3+CRA9TVsSAnZWagAAWb0QAIjdJLTDXNaEjsF3QsdO\npgvviPwJW7JxyKyCRxQso9tO6F+ToWCz7HKzOVc4ZWvd9V+K8JRHy6BSkEXs\nXbxXDRLngSjD7vJOq5Lnv6xhKPvuaiA08olOBX8Hvt8eyRDChyapLGypEq2u\nSviD45hLIlRKaAiFulVbTzOZhsTsfX4iTFDJtXTkQg4MhM/OZk7d+xwSb3QS\nMIL3EHFN9LKa+II1xHswCmF2wzMw+c8OJjFzUwsmA5+0fVE3TltsRlTyUoH6\nhCWbxWreZf8IwzXLcmrWBkijUgming/nCaEo2Nrqfk3/m0TmXUAqfAQgOeTa\nSiiNOba7Y3xhHXX7vaCOZ+OCaoMYMUohTtX4shFKciUFa06uOKVqMaYu/zqq\neOYd+uAGLEXUWdAdbBWK22SzzQm1NMBi0h+wulaIGKrAdB0bbQI8HplAPXk7\ntqSFP5PafwYmTKmxv0+xvEIbrEP+Z8quRDkBWjMU5ZmvIFSajVEAFgx11gh1\n/zPLwDgr94geKgOMghRjNUCPp1ciGzPMMQCT+vJFTz8PWgoHNkofeR0Ph29p\nks1lqIHHZtUBG1TR4oUZ3dlaclgb95dmzvyKiceHaYpGfcd51dSZjMQSWY8p\numibMXFzRteJJ7WkrebPtFGE95t1rfjhUx5m3LotnbI6eYWqDU8+ec2jG6Jn\no/+x\r\n=triB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCpCqkoD75gl0GOwQtxer6Fv1AtIeuyfe+kfkQi6zx2hgIhAMHaH9bfiEhyMtIGGsXwNV4zyJXbaOI6MSGhJa7fGQb+"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.12-alpha.3-acf_1529466366112_0.021274091240564008"},"_hasShrinkwrap":false},"0.11.12-alpha.4-agile":{"name":"teambition-sdk","version":"0.11.12-alpha.4-agile","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.12-alpha.4-agile","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-bJdfCSQshgFwYFe2TKQ6eC1woRZjWt8GNZMATqPEmLu5fM+FYdn5Mp1QVaAdgG+DD4j9fXuWOIvkxvhVYamS1Q==","shasum":"340c1f5691177a3e7c274c73d4ab70c70392bd3b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.12-alpha.4-agile.tgz","fileCount":326,"unpackedSize":639739,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbK1iLCRA9TVsSAnZWagAApAMP/Ra6euWhseXc/EZXhLCa\n3lquedNp0Ex5+2z4s877eXMgjn4kUKVCdXlM7yHILtwSHD6GD9mLxc6p5Dof\n6MXgKlbe+3uTnAX1ZbaXvSnlZO/tL3vyYIw7DdBFUFZfnroQgCOcA3qNUUjM\nJawXZ8PW4WpH2zN7TwcPyRSolCaCvIn05KIlho7Na7lMqfaWMh6WE870Amv7\nv9580FHh1lNnzcWxZcc0jYgnoLAUv5yMh8EgZYEDXPyDpYUlpxsyUhprJHFQ\n2Vq8v/J54X8pN451VRwhouirxYdpglVmNPVJQNEDLKOXAlFj32nGdBz8ihHV\nxqMAjH8q3GHWIwJkHlwg6G7ipKxvCJBmqLGmYWdRzn7GhWvtMXWHX2qyh/Kb\nhz2+DrFavmAEcYt5xFD1Ocl8sUPTU9+Zto++4YDZsT+C7WEs7HbQcIxp77fu\nqVf0w0EPD/lF9Lr7KEqH7e/oVu/eL7oX4YkzvHkv+uqVHkyVNUTJGZk5rbMo\nuuDsHkA7BiXR12i2qNlhCDU8A23ihDYfOSkOa9ZQhTapOgsaBF8SF486M61a\nVZZuSQEoDlKKPRvwgiDd4L8zIbsmdzNWcps6BlC3AykyEZbgYElV6H4aLMMZ\nJV0/y3TNACsAi82F5/aE8D7zqRF2PArHntq273MMi9z6jqlOCYKvgFQs8g2E\nr1+k\r\n=qmJf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBjLaiB0HKuTGXVrWK68X7p0TGeNkFUoaXsUPQ+DehR7AiEAvwBJdTvt4Gjk5dAofyMEv+MzY+I/dwXVP/AStsoxRv0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.12-alpha.4-agile_1529567371329_0.5243865115369399"},"_hasShrinkwrap":false},"0.12.4-alpha.1-idtyping":{"name":"teambition-sdk","version":"0.12.4-alpha.1-idtyping","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.4-alpha.1-idtyping","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-xgAFe6luI+bT9QwdJUebbdqpFcXGBUrLNCQz8GSwT3Hi4jFCIkWJGl+AjL7G+ItHLojBrKzTe6SG98jBO0vP1g==","shasum":"02f0a3f0703c9ac268fbfb4cb91174c6e9997b4a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.4-alpha.1-idtyping.tgz","fileCount":344,"unpackedSize":679972,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbL4QrCRA9TVsSAnZWagAAgaYP+wUPCVY3f287uxb7hkQX\n4n2VCpEAfKl3I8B3NNKp3VKm9YDpFFzG6KaA/4TbzoXsxBgyKI+5tA6v3V8x\ndYC5O3Hv7kNwCNkfrvmRIbwKUNaUfBkbLo6QJmUcs6cjG0flHX81UEAs5iQI\nJwAdU28jpr8QZtvuruV6uIqXZmbaUZmLwAHw7KOAd7lWkNCnOfn7glWi+kIX\n3G+P8JDIn7L07iwlPg3cZOuu5TOghxVTq/j4hxgj5AAeXxuzl4qwkXHxA8hg\nZV5AxxaBXUH3Cz/Zw7zJYJpjxJv3yziYm6hZWmZy+vftdgESiHJG3bRixd7V\nbTi0bBwKN2qYNe8Bc0gr+jSyyq4vwV/PMFVo+jJ+MEYA8lQdt45VhTaNnXia\ncszB+bMdoDH3d+LjsqqwlVTGWBWxc2s+L+u6iQHJDaQjeejIzTYXU0srU7A0\nYyjehbeRx9zK6pXBe1nhN7QJFgeQPucadiacwZPM7f+ceInhJziP8JFKVhsI\nZVtzuMB9sTN7k3F29HZj+sf9An8XCchbjRLbSJtorStxbKnt98w2ZMlICXrB\n4m9fmss8OZtcJURH0TJXK/RGVB0UKCFxgbO5vWi50sPmRVVH4zvr9Ymzbcm6\n/4PgvXzYAAx+zP7RFvoLzSGp+NJJEbDv1XOX1yZyU1AK75f/BTV2S4Nn/EQV\njjVl\r\n=BJqo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCoPQYl6At73RbHI9zMK6RUdyjQSn8VE2Wcd0VvhCMngQIhAOTAhauhHfD4xm1XOQ4n0/rHC6UqeNsRrhfPfzYpXawk"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.4-alpha.1-idtyping_1529840683291_0.6851154394991965"},"_hasShrinkwrap":false},"0.11.12":{"name":"teambition-sdk","version":"0.11.12","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.12","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-pU/uQkIfT90DoEZVD2ffvQoXtrYLIHhmfsogMt7alT35ZZAvJfQhqdtqPaTZS7XzCL75TLhzz5ccQID9L9kMEw==","shasum":"037a2dec051d191d4809144752061df34d895012","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.12.tgz","fileCount":326,"unpackedSize":639012,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbMEgjCRA9TVsSAnZWagAASUsQAJ/bj/kniojYgF/ytQZv\nGPWO1fIqH3nXqLPH2BiumgYXzSbSZ2M4su8d6uk94sKIoXqT6Ezvw3QNnsJG\n/ibOtyngIF1ftVwzYkp5MAqfgyT/LTWC9fYJGMY37I92Y2HgazVNgPuT5gXu\n4Hswlcjl8dHd0290aAUri0MkzRDe3XFL1jNcfmwjx6oOIr7jjKxa/UuY+gCv\nxMw6Urqo0xz/ifHMTPYmk39DSCrXGYCC61mv/LCbe+mAOsfpUQ7M2d8I6987\nFN6zYsLiCYTQxppNsZWhi0jf6iWzwnZakwgeSWlANMPQscHk6sVitTR5KmqV\nFoQ+1Dx5XzGoLa1EOOqlh0jrc1j82/o5jG0//NOiR42Col5O/NkvdFM4/oWA\nT1lsYbVhY4+LcxQXeoqtHi2HhiyZC3abRTWt/miURq0o7Mylr1CeInpk6+vI\ndV3rATfeljX0MobzumuMxquwLNzfeig39CqebIPH8myIO18bJrmsUslNH/N1\nJKJ/olITyZ0D01h1/awRPRS9HstjeSY2UGjKaPWbi08r9jOzEXdPAmJlISui\n7nY7LhukCm9MiOiXuGD+SpjUpbaJNwYJEh5eQlTQU18m5qKnI6rgEILOGccR\nusqXzLcIn1Mc6cN3ync1sRWQY1VfFt/hHMo63To7eMpnqdT3KXlcOFt+6bvD\nEX+L\r\n=UKm3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBH498gQovjW7nJCpLXhNxpQKIbUaudJoYmHVvvW8DipAiEA1XknZVL8vhCfkNtNBLZDj6viAfRRtI0aegJEy12EW2I="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.12_1529890851208_0.01138769106908355"},"_hasShrinkwrap":false},"0.12.4":{"name":"teambition-sdk","version":"0.12.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.4","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-YSh1RAZlWWrBglA0Cnc0Vz5VhVr9pv5lgllEC3L9+RuHof/V+vY1pmJ4j6Pny1NMRVDyuAz4z/q910Pm3PMOJQ==","shasum":"f79df922664a54327853f1df4305d2d17d03036b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.4.tgz","fileCount":359,"unpackedSize":716078,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbMwS1CRA9TVsSAnZWagAAfZEP/19vU49IjzSF7iX1axcT\ndjmV4f5DTiBZZqqili+zQG/4PlYAZgcNSyFHuWyq1KanezBLus+Guprxyd7B\nEXPjeoeIksmTwjeKottp7sY/XvXdJyP3plZaaMdg/cRGheTm1xY+9DV75lIF\npnq/xTfHiZc4dnIX04YPRZkN5d4QSsUWPNfFGGfiqagEKth3beN5gLP13Xaq\nrvO/B+KZWky8bJ/lh1+7xlXwARcOdIf8uAkCwRRXASiPGz5D0yyjUXzB82Ht\nblH9Roz90xeC2uHm66z/TJwKTnPiOeRXuVGBF8HzIVXilsqU3Ir2pQcdFiEH\nFhAEb+5iIyGYj2/cZfscGQXSimUPNW+EJCkICg06vGPDNQ2r+HE1Vg6JyMRl\nSo23ZSA78QEczFqGfA3Y4HeYuj2NkrTNXWhhrmzTy+8JnKIHzMCfhdAABi6Z\nIIYrJY2lyRcRobkF/625RTSitq0Ud508pwKZKqpgkzmik/MqUJ6QRljRPAoV\n5oKLWj4fk9tAVLqAkSdHzStljfsW0ACGHh2Up2zlKBHbrAjfzLf8xiiHu031\nLId44VRDeuC0lS0jDAsBUTZuv2SzKyjZfh7wNR12vVR9rdVmFLoWAnKv/aV7\nXQP3UR+DZBWmE6dCQKN+j+O+FSx+3PAcAfUK7w5qus9Ie7NtDMqQO7GW2OE+\nzbun\r\n=qRmO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAYZ9Jb31WU4HpFh/zKJfaSWbvPylKm2D3xaTdDkaaxlAiEA7WBdTwawFsRs8Gj0XduxMjAWvrn3EFZUCj+2BT3YOhk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.4_1530070197325_0.9522794471834992"},"_hasShrinkwrap":false},"0.12.5":{"name":"teambition-sdk","version":"0.12.5","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.5","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-k8fsjYYBL+K2BWY0e+WZUytIsSwi7VVEBhrZhChuxVjLdix1K02iqUo2nfePkUzT5awrmkpkG3S6hMJiozeabA==","shasum":"552ea29964b7689be57ce513d62d35cc1ff71c4e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.5.tgz","fileCount":359,"unpackedSize":719228,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbNHSNCRA9TVsSAnZWagAAZYsP/3g5XOtcoJLjXdM/wb+p\nc1BXCFAyCEOtoh68LDlJqokmmh4svcPLqwlzC51IUnkR3t/Ns/FS2x14hCMU\nlTLWzaMvMYE7RwtS3kpalDVpYkf/Oua3VUrc2EE6w+fPAc3zYmuxi8qlc/KJ\nay70cPzmWwuBJSP8EV1ig9BzpHP10Bocf2iNem2S4dUAQkz9kWOP26vWYS/q\nvzVSQ5rBV9+DcXu/kr1f1Ie+/koiC3i5aXkZn8wQh0vughtDwQTDbQeENW2c\n8ofqnwOx5Bt5rFvEaPel9Blq26Tme06zr97CIGDo6VbrwOsWh3mHYPLody3a\nq5tnaNXuh4lSAwJglfp9ukS4eYXyLe5Rt0mU6GRTWFv/mwDvkX6tjZ+LDnvE\n2COOCG8AgsKifHWZ9/kHF4O83ojSpc4Hlri3cGgabwtZT4wW+BPuoFf1sfpb\nWmTPW/Xdi3goMgvu7bWeZYz65x3hfQbyQte1GTt/rLzAdMNMRyDd55YQcy+w\nJhAsvSV3UP1nXHIIm7+z0ROi9pu+V5nUekXEzdAeQUmWiMT1zijWxvrqYCFK\navE/apQnT1hXKd0RpiYjjPl3ocNRy4nqTg0/SrVILotUCaa2w7LrZEKqHSn1\ntl8dBzR3LZFyvDZZMM+oQQQTe/O/de+0jsBmezJRCVYrD/7SRNsmcLWiw1p+\n+OQN\r\n=E+/I\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCEb7kSI0lXnY0vnk/LU1VaDY5ogzw8A5tNgf33qqIkbAIgLrJMNb4/VegNBFV9SNYjzGOuMBkVu2iIPhIlQPicoVc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.5_1530164364932_0.12240936767558686"},"_hasShrinkwrap":false},"0.11.13-alpha.0-orgsfc":{"name":"teambition-sdk","version":"0.11.13-alpha.0-orgsfc","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.9.13","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.6.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180101.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^1.6.0","moment":"^2.18.1","node-watch":"^0.5.5","nyc":"^11.2.1","reactivedb":"~0.9.13","rollup":"^0.54.0","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.2.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^4.0.0","tslib":"^1.7.1","tslint":"^5.7.0","tslint-eslint-rules":"^4.1.1","typescript":"^2.6.2"},"_id":"teambition-sdk@0.11.13-alpha.0-orgsfc","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-vGMbUlEXDVT+Dn9tz3mL6sl+plRi9HPdctzs1zYTKmqFxqS+hZl9Xc5kK5WIADmw2Nl9ZJu6TQtrSn2c5+/HlQ==","shasum":"0eed86aa6ae066fb7c0110b128d2142882a729ab","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.11.13-alpha.0-orgsfc.tgz","fileCount":338,"unpackedSize":668362,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbNLxjCRA9TVsSAnZWagAAI60P+wcBYcNzXpEVvmLERluF\nbr+Jt2zSpoDn/OAxolAg8XBYBpVoDmRwcTITyviJ2wCGJDaayYcOXIm1Xp5H\nH3gjYIHU+8UO1HFlqZYP9X7tbbItMrOBJT5t6ZW5ZiTqECUNEwhRtKX8S6B1\ncZNCmHXWJ21JLCHAZwGn63A4Y9Hup517CRhIZ+vRCBDLuRlIGsmbEJqT8max\nNuEkgkXWnoGjRylU/5sah+TUjxFHR5NAywmyzYqLRCJvc/PrhWqwUaVtJJdi\nP8OEzwQRW6z5ce/4t6CljlfdN1WcI9Q0S1UbS0JJ6dl+R+F7vBSH7Fqsnkpr\nJFxkQnnj0jVu3VFAcu+ua+UD9mFmAXGKdIGra9c338fU0klP8Qiv6iihWnO9\n+GAeCnuhFaJSEzsrq+AXNO8MCx1CVjeJFcb3/nNJh2/BsfrqKSLjTEPqkxbv\nuVSamOuIwOqZc8BD02tOKfERUT+72bKJkRjNlbh/fB4gDlKe+UPYi0CglTgA\nwYPh13GmkLK+ZYmf7RYhffZc11e1oGF4Am5ReiHBNOlVe/k8jMFvuLQrkynG\nmLmNm9XwyuCOh0PU9LEhtTMsbZ0F2Nd3O5wVQohBgBP8t6/wiGkoihP6tanI\nvgRnxIVO4c+cNX4ElpHsLsg66Qn3vUrRfTKiO8R15gZRrQX4V37/Z09Nnhog\nMpb8\r\n=BZcW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDHhTctxwcGNBPB2KdIqQoTRALXI3Q6Dz+w2k1Mm65B2AiEApgBz0M6/3jzJGwDBiUuHu4yzzaAtHZZwF0D7X3+DuR0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.11.13-alpha.0-orgsfc_1530182755280_0.034421472997355984"},"_hasShrinkwrap":false},"0.12.6":{"name":"teambition-sdk","version":"0.12.6","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.6","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-HRUbWW/D7iqu+nz+8uAEahVxXVSR6uJDOnD1hreibZPcsrsIpxRKbO6BJIz5hIyUAOfwD403QxQtgQN0/WBxQQ==","shasum":"6c79955598bd1a3d244ac18619c2cfb289ca32b4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.6.tgz","fileCount":359,"unpackedSize":718471,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbNOUbCRA9TVsSAnZWagAANxAP/Azi7inP190/eCJWaLkN\njQkcs93dJV/pSFkxFaT3OzaUX4e01U83SDiGR1AuC3hUP/cdAm14O1KOy+XE\nq5hJjlqgT3dld1A3zVSV4FkIk6QgLL07GW5gv8GGpYgkzdnbE8Q6WPMHHlqt\nmjoxo4jhw/dFn5ebjwuG9KNjcNJRL9V4Re/jiX79Wz5sLcpbLyPJnV86wohg\ny2yFLAK1ZMYhqU0CQLN+bRZQiAaza0qUFI7LcCq2UtQbUAqljTQtTln8Xeet\ntp66/dFinb1D8gCZ4RSn9hXSDPW6DXckqAFPOU5+zKjtmt9yF1zJvu7yPBm2\nWY38NysiEA3elmBMA1maONnyve0trZoshMR6zsgc7jtV5GrhIeuTrwSlzZD1\npcuToS1u3bXrhLmk3bBIWhORZjdHEHI/wedH+7X1SPqQWdpmSLcR0VNtNN0E\nc1wKmD6SjTFAd55/PaJf/GR/URgwwYGSf8cXEG3+OvNz6W3hz6crE8sG4463\nmQUt2ZwShoDjBBsnzENiDYpoDLc4hSgIWJAVlcLdKDUEqLyhepQlWU3WPLiT\nMzVfGaLqrczF8eZGtMyLYpfxxtCBzkEYpEoH9lAbFvkflSgKstQiSTRa4c3G\nsnwrmXQX2lCPafZo2QoWhz8TM7YU6SmyFVrsHrGwmcZIAkDVt5kr2djXHfA+\nU/oM\r\n=pYg8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH53PnXwVi6glOxSMtYKjy1zd1c9w5MTRzVczFeoMzkTAiA2tdzqltU4+FN+YPX/rwwcZn3NHkQlpsTk2DF5zns0RQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.6_1530193179278_0.3533514988502955"},"_hasShrinkwrap":false},"0.12.7-alpha.0-egenperf":{"name":"teambition-sdk","version":"0.12.7-alpha.0-egenperf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.7-alpha.0-egenperf","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-5bomtALPZ6R7J39Bd8nR95ptHTgjD7L3aM1yUXfDxQzOmICIDWOeIPPb5gcpTysUsjZsSuOAKAkn9S1mf9Eg3g==","shasum":"d7ec917ad9397e7de188d9340d86df105541ab82","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.7-alpha.0-egenperf.tgz","fileCount":359,"unpackedSize":721028,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPKHBCRA9TVsSAnZWagAA04YP/1OXcfKXPHUSy/anww1x\nq0EeHrpBM9mVArZiudETg1Lv5JMMGQbMyysIz7liN/yMkHoq2xQ+iAhWx63L\nQB7AfeWGAUIYeQ/vrdLrwnhfwuuRmGKRQxAyuT6Qcb6RWqcCD6CiKkh6bkdY\nN0lDkAoD1RM+cbfhhRiOl75CRymoXXs/mpCqLLcDG5uz2XveIxJK4Usyj+ke\ngGOxx4iRRa10QVxRYV6IYzI0BEdxoBXyTQIdyHvUfK5rg902RASOokPig2Uh\n320cRc3EG0H9xAKktr7CPf10VWMKq4v3HrzWLQMn8Fdqm2UDrdyEOBUU1mOo\nj7l1asbRCTtDuj7VjUAHBOGSM1+PoDU36OqLTJdBLYLP+rRRnhH8iKfNXkJk\nBmhyoH/mbmitkFystKBzBYAHURNuTj+2ZX5j0APHxHCJjSzIHutEQXDWJuK/\n0Qs/F78oLThr3h1X4P7R9o6cSj5UGYhqDp4nKoD/xeRlDhjINDS5GEfe+m1w\nU6+KESj3NVy/YpBBsmwU2FDdDKdbywiJ5RN73TO6VR0yjz6oHzlKLS09vnmW\nmryJ+d/4ewzLl9AE7Ub3sI1CJH7YFwSqufx/gsAXjrQRhgofNWKkMeJFgQj+\nHp6kgozdX9r+6Z3u+O/eNoZYETJLyVcgJNyEPKIQQ/gbrLAWKZEoUr0L35OX\n5WDG\r\n=N8E5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGg1l/yrMHeEUeN8jTJs8KiWivwRFn4bZKOLmSJSzf8XAiBxTC5GW91nbgj2qjnSNXXG0OD83dnLSzhawwQID4t93Q=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.7-alpha.0-egenperf_1530700225210_0.03483679083551139"},"_hasShrinkwrap":false},"0.12.7":{"name":"teambition-sdk","version":"0.12.7","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.7","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-OgBraJ8lSPWGaqhZQP4l3fvQ05YLMytiicDITHSa9rqOxNEi9bqeuCZ1SdHvcxWXtUvsdD2qmmntUnIHLaS6dA==","shasum":"d4abcf3b7ee874d51d187b9554eb5e555d7ed184","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.7.tgz","fileCount":359,"unpackedSize":719468,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPLh+CRA9TVsSAnZWagAAIAIP/1Jj4Lk/1aMMaVbPtxxY\nLPDN5VcndrPZikUpxqCeokuiwj+nq4l5flIVpqKFxdfqKkI6CZVf1du2r3yr\nGo5YWFP8dXMAI003s/DtMdqlxzXgFD9Z1069jsx/e/AyLI9GxmJUbv5DUHYC\nRwE5xYIL+TKrLLbLswdQA2kVWjjNmYrC1cjW01pJXrfxwwBKCxJSxxRfbKRQ\nSZ9v96X/EePS3qaLeAtWULzQqBcz8k3cf9d8TZhcIpH2sCvtcviItRF6AUxC\nKPWvLxmzfQXYlxrysMZRYnm924yCKVoRVDYGCUI1QRfGEUXTd6xeeminCDk1\nVoO5jIYGFkfCbMo/tfIN67fVgterXj+qoUHDkwqwZ9rSGxi5OL0A2XBmHZrv\nkjfp59mPVQYtp3LkjHFcboqExFmUvLQvcQ8uv+LIharz99bDODxzYRchzk49\nYsi+Xvkr/yNp2tEF/XWeymp4C8v5pXWy7H4sATd1aHaeNl501cxMSB/kxxMW\nMThKa2HGfCMvl2uQegAP4oRdgKqC/Az0uYPLGPm1/MWpEpSV8kAwcl82+gob\nXB2PFh//UuDaYKamjFU5afLL4hvMSvDne7vAAMKIPh3OYFqXUJz2vkDW/vRb\nTqEPIg3tzP61LbalU+lt+xCeJhzdQqKpgMdO5dSRMr++FSBjGjhRgLFrTOus\nSZVA\r\n=XQTu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDUZTLNP6bgw7E3S54+gHrWRLLkD6+5AUITLFvLjGRMJQIgf6XUKLF1OYp61XzQ1/m5heQyulsjztkuIIEk+5r5CE0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.7_1530706046763_0.12561247728934277"},"_hasShrinkwrap":false},"0.12.8-alpha.0-pagination":{"name":"teambition-sdk","version":"0.12.8-alpha.0-pagination","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.8-alpha.0-pagination","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-Zr8CpJdEkqqH46oPfIyF3G8+Uhvd1oNKt9BbDhpeYVE/8qBvjy+GHmsKoPz11HI9r3yDdOSCEpLV/j/eTjHZEA==","shasum":"88a0899f8cbb1931dc7daffd3489bca844c3e6a5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.8-alpha.0-pagination.tgz","fileCount":359,"unpackedSize":719599,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPXOOCRA9TVsSAnZWagAAWhkP+wcz/3mryRcEuaDQ5JW/\n7SVjd0Ns2PXXg5S9F9EYdbHUhxw6NyZxkbEEzBUQWPeY6ojUCUH9LR6dSLCS\nWZQxVvMrs+nD/OfNaLEg8JTP7bF6mtsXBiGEblggHpWLFL5NAWBL3wu4JKQB\n80Dbwo9ihmyeknpJLCcfkAdJ5fytrTIzq/qSqOPzo285kFalQIIW1F9p8Ofb\nJtr3ch1gLJmjkai7UMI8C0TQm8tlY4mbqrZ5JZ9qFuZLS61Ul3ckDzaUyhaf\nls4LRH5ivcZpwlqe4llFGPHJV9K+61ZhGQmyVN/phED1Ymj7qD8fDTXXaMi2\nwXzAWKXupITQ2f5cQjG0OtCV9I+DateXXuE1JUKF6dpp7aStMVuCetTfz7bu\nUzJBKNEL6YqgkVSYB6TMjAR3hMOIyW2imKB3uyy6PWJ0whyVVsRZ7PSerM0x\n4Ebm8+TsvvyQB30PU1woNoqhqVaUNVvCrdKMGZaRHeFbAUC5XfZ8lKWimUHe\nbImidmEjC2F/oohXwNIyX9EdVI0kczehTHGuMbdRD7mHIYbcn6tD0HyvT3kB\nXk89Jlzzjr9vNMzPkYzv0bphNZ6GC/E8zQcUGCR3kiXvV8EEZMPqBCgVYHED\nHxSrWiEqo6EEkKFp6Yd0mfL5T/CWVso6KWM5nj7cZZCDO9CkDm369jk6OKRj\ne6ns\r\n=9+IZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDEJJ7fINcVL545c/94Ad8EOv4G99sOdGdt2QZDB/7HggIhAOGQ/jDy6nv4a2TOlOgni9ugIotstm8+4PHjFbXNU9Wj"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.8-alpha.0-pagination_1530753934444_0.17622917008246253"},"_hasShrinkwrap":false},"0.12.8-alpha.1-page":{"name":"teambition-sdk","version":"0.12.8-alpha.1-page","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.8-alpha.1-page","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-2A9L8ObhBO9Ps5GEpvcaaffOX2OMzohsMJqGHwY580Fxd+Uj6g0B/USC7Sb/VptpRszppQCm/pSsXfEo2HBg2w==","shasum":"8d765a49ca5595e9d994651be5254619e06ca7e3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.8-alpha.1-page.tgz","fileCount":365,"unpackedSize":741704,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPYF/CRA9TVsSAnZWagAAbQ8P/AggAjPOE2yQn1+kCL8J\nLjAcDimwQAAICWyd4kldpr8ovcrMCrk0vK/w+bqBVMaHH5VgMWJM//goXw/+\nnxlgdjHsaDwaQ+YW3d2Dgqb7axQRKmauPLDCBxtD3VOP310cu6KyabQlSzW/\nSTClVvIBVq7S2qfvoiDIhoOYBNkHXmDB2n3ZVmY9sSY8JCFLUOU+I074UhYP\nBVH/1vCgDXt8dLZrBMDVh6T6LGoy5BsYI1/FK3o8kH6Ccv2PkX6Th9NjqGfJ\n1FfzCN4YaTKdAsGNMmQ8taU4P3zBp6B7g+s5f0kge0qf/3+eR9sKb/Pn0yvH\njBQRK8U0XxN6Lpj9qvFpii1kt8xlFNWJa6AaKfkrwXA1de9R5zZslZB38Pdq\nxmdA6oHY9rBVCaoMc2vW+c+HX9XP8yRuqkv3qEE18wCmViGLU7fTJZ85DjXF\n8hJrmfAf7wrB/4DAz2dttku9Vf6pKKde63jy6U405C2ou5+wTCBM/0wSmI9M\nDAvFpeggaG5SQjDEDgQRurEBp43y6BmzzZxQjhNo1jsLLn8YtvXOiLH9sTU5\nj5/zCUk/lN+4ISGiVlvD3fEcrFpXtmIHPYiIgQ0HQWFXDibe/kRPiEWhM61+\nUUdDQkLX66bs+27axQMitQIdJySRzRQdPJhe08dJism/I3Zmdhw+/t2kJPYx\n/HAT\r\n=FXVh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDACw5DYozSUCsRutoCv7MyHpfEV0XP6nVpMnaqv1qOvgIhALySOnZ1DlvgxnZ4Hm2yrx4KtCKQ/Q2OFA+WJ8aMxDQH"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.8-alpha.1-page_1530757503293_0.24886445722526296"},"_hasShrinkwrap":false},"0.12.8":{"name":"teambition-sdk","version":"0.12.8","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.8","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-yTZCPBxOCMda/7XMq4Q6pWohZA9prJuCN/czJ1Ti2vvD+XEH0iWQ6UahqHvK8FfvWB88QmXjPq6h/dDWxPbICg==","shasum":"87d29602355147f3c4d5c33b48dba1d5759a39e3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.8.tgz","fileCount":359,"unpackedSize":720757,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPcAvCRA9TVsSAnZWagAAPC8P/0e+UVKJ4UbHcOcYoTeL\n9xqZJSVZyXzmdL1Fl9gp8h0KAF59PhtESuEN7RYuuhos28NVYRh61g1pgbSz\n+ypd37teL2qxTP+Sg8+JzuQoEB/seLfeO4RtvrA97s3YcBGCN25FPYiTNZxL\nsbt9+KGWVmx37yQza4Fl4We/Xcdb+ltQ9zDHp38PB5JbrwzQT9Wbf+xgN79v\n2fbHjaHGNCDwrfY8fvYDiTBxHYaNFOMc2BQw1hlOyj/nNPJzhcQK4EgCB6JL\nufi2fYSELRJRThHtjBwJvT2PsfQLNEYQ3t+9+CZQgjCcgbV8rWNnaMcu2AbR\nM6Wb67n0uyB8SAGPSDKBTJ1vObJiIE4Vflf833CpcEWdP2KBzP8ZfGmjlEed\nWf+WU7uWqA/pzraB6yZnxozua5cpstGefYsI2eooP57unjah6MGVoXHvORZc\nEsNtlJQlnLEnD5IH6etA8Tpbf3lBHRPWDIjlB7e6/mhaYAh1VkCW2mqArXm+\n/r1FbHLuMxJ8D17NTnGpgXj119yAZ1vIyyW1xOxfhwh77kNBcM6fGYwiAetw\nbT6GxJc01nUE7uxeju6wWgEwBHX8HjQResupe4K4Z/XxkJ3JWranY3BvDaz7\nvYnaDn6LoZbID38G9mASwYE2i8BI6ZrN+wz0ZWG2VBdrFG0FRbuL/uGIo4wn\nFeeF\r\n=exke\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDO/fjwRCLXTCgAezYI+M7ypmTpL95pkmpZTEHcDAOOwwIhANzkTg7QEnP0WV9K7NmAiPSAQVCKxrq50rc9428ZlkFu"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.8_1530773551489_0.20053288168829408"},"_hasShrinkwrap":false},"0.12.9-alpha.0-cgrp":{"name":"teambition-sdk","version":"0.12.9-alpha.0-cgrp","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.9-alpha.0-cgrp","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-tEmO9+WtrGYFUf5VBbLcoOPaY7WFo04DkITaQRePVqTqvhsB5EKINk0sZFrUHwI4BC8cOWkDi+XxaiW4siLIuQ==","shasum":"574e8ce630000e0f2aeac80fe36774833421dcc8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.9-alpha.0-cgrp.tgz","fileCount":362,"unpackedSize":724447,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPzmrCRA9TVsSAnZWagAAR+4P/3avtAtRd3oJytJtz+3I\n09yiGFXkH3/hEdC874+ZEW+Mb+xUgafhJF42heJnUchdd+AaGaPUNKXfg8gJ\nTk6oYSMKDJuf/bkTZKgxaTVCjraUh5r1xhP3Apl6VW5ruBtrhZ8Kpp9bHYdn\nhOafPnYuzTaVvsIDE+YpTAkcAIbaF6UMDmu8oDvObpbnQPLf8//BFv8srdbc\nlORjjhLr6CdrD6HGAfR3XqnjFn3S/1UX3TEu634VL8Thb7Y6bLNQ1QbO3vvi\nM765GGy8+8wtZM/UOQUU8MFhAtjrESqDlsCv2mMStqlHMMZDc4dQkZDBcK6e\nkQ5li0e987OR+gHRBrchJMNU+aEUl7bPJHTVp5xPTbJdE8L3mz2VE2agg7T4\nvFWzYm95yLZxs8wJFkzdcqsab0VVrJC1byz0Pgw7nrYS+6SI9BWrb/WkHGJX\nByIQgMrqhxw/VqcErpToRIGbR1DPcOSiGVh2I+asTTwdCAbDjrefJPanKRPB\nt/xsAG4E8sjjXtop0mEzrmzKnPMn+uJPV0aT5iMg3/cKcNL8f0G1OlhNtRRa\ndprDWae2BzT0YdtWbNsMCvyqsbPyBNcMA0E3t186gZJk3ksur1nRK0fkv5i+\nGlo21z1G1pXzPkzYacTSyeML1LI2BQmOCP86iBTaKTCrBuyS5mj4TvJhjFIq\nqQv+\r\n=GXF+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEHVKRgoM6KIYMd2+AnOdeifSmaARJZwzJ1t/N5hb/M+AiBvA/BefAWZxzsnjWZX75bfe0jFS0qqOInUc58gDlfNkw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.9-alpha.0-cgrp_1530870186986_0.8892641911578318"},"_hasShrinkwrap":false},"0.12.9-alpha.1-page":{"name":"teambition-sdk","version":"0.12.9-alpha.1-page","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.9-alpha.1-page","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-5I06booHasHRY4YN0yrRH/MwS1u/FhmPiUmJYQ/bs5qYEnmLxIJnsjnqkKCzB4fdG2Tz2pUW2zrBIZmwHPLtdQ==","shasum":"e33b5ee8bc8928e48628471fbb1449d2f70993e7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.9-alpha.1-page.tgz","fileCount":365,"unpackedSize":741907,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbRCoWCRA9TVsSAnZWagAAffQP/0qNrKQ8qgYCMQYnd1or\nT3qPQu4dIDQDMB0pi9C5WsaSobL52AK9IysgNvuLqomGvjz10cfYiMSaX1BX\nS9Bvu0fMBoo37uuMHulG6TzZTfXltRyDHGGgbZSQdp/IYEdCcDMroiVyHTv/\nT+3KjOFIcilGY3V7jjSmPiKEG/eFlICzxpvkhXDVhk8IHkQziWwL4Ezr4pp6\nsym7pmKqxZG7k7i7jJM3iOCu9u314T3UQCSuHomCiZR2n3fVjcDJMzOR/LAc\nL1LHUP+NJpx9wYRgVnkkHlQ88QcaPFZ5ceTmMDIAepyh23Z55Pd3L0AmAZRx\navITiFGR9G8EKIwiRCdTX/ys+Ifvcp3srQL7RDSE5LOU0zQcZo3l0VZM2as0\ntwg+l/elu76zXr1dO6LeAjPoOW2VDf0VaVdM64Y7QD2IerJxlr1yZul8+L1L\n+SdQkfJmKNiKFPmBia5o0mlBWp8jK6HrrZs/42hump+EIn/s1rieROdJwyTw\nP46woiRpApJjSyiP1i2WQHNsrqdX0NRwzHjGd6ZLzlg8kYWa/mDAFraK6IGI\nK74nRMfVHrUXmR6GqKhqzGQifrypz2JWytFMzXbTlmCVvxm8xIWVm0KOvkx8\nqywcQmgqu9asSXHuimTa8aW79R8AR6u6E4/0A5rsrZTeiWmR8Gj7V34n6gx2\nvhFZ\r\n=WQiU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCpiZaoew6X080dT/aF2hvBPHn8rgh3o7qAyj+rY6ZPxQIgZbU+LIPQm4B09fnzMDSssDcp3cqDcLO/BTo42kbLmQw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.9-alpha.1-page_1531193877997_0.4773532158695888"},"_hasShrinkwrap":false},"0.12.9":{"name":"teambition-sdk","version":"0.12.9","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.9","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-M2timMcp4xEW2QUhWPebyjhtrtYOzZw4akAu+4AzFIvwuO4XcZyRJLolF4UPB/5E5IbHzRH0gBJgXhEeyz7ArA==","shasum":"6b7af574721183a5138526e821f39225bfd3cc40","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.9.tgz","fileCount":359,"unpackedSize":720787,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbRMclCRA9TVsSAnZWagAAZ1cP/2N2AARDqskf2VSfi4qT\nxNGof8FDp3vWz6C4AGM+/SALA7I94MMNglgCpziKeikFstmdQZEEICPNnw9A\nkLFL/0Fb2nPlPI/8xNk/DEl9GOzIZaxIzfb7T6WWIkckb1xEtcHt33FZVN0I\nWklkF6qXkwyz3aW9nmL3fPluulj3rT2F4GaXuCdWtMR6P1nNJJLyaZ/3jkg7\n+77LS+eCwaKRe4HdXHddRBNkCpjeyC+PjyLv3c9ymlI7DBFsGA29QazsdIRn\nAPmLBncAlqZk0kXOaxWZ2fTKqgjulXGzcbyW3IMylaeHOuUTiUGlnSPXz+7F\n/JgJU/bRvikBdZdfaFUq/LtaPExP2zCqJfbigEk8jLJoKEWH5tbQIoN+n0aV\nNMNyhkQGeTicrG0lzJewvYCi9sUjk04DsGNcW1xVG/YDAz1feqhG0C5GGK81\nFgYtYPfQLs4HHqkj7QZNQHtPO7N4yWloE09n27iote9Xd8jGdYY34tsz/Ei7\nfRQPM6LhJKhDoCiQukAIlcxNIxMDeMxWi6nLHT47HeYEXISu+AjpM8zOeUfp\nAjfGw3+Z8bjGU4sWdR+iOQnYXfeksLWAgXfTiecx/iNWSxRoc2vXt0ngwoES\n3eFvpBKJce3YUcMruemJTt9LBj1UcHdFEjtMWbPzHg6PK6+z8bV+aQusVwNj\nSqPE\r\n=KNGr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDSymMPk/S/TqqNcAsaCUVGBa5AaFjRVOMujJf58tvV1AiEA9q5pDA28DHOwNROJdCjJ70wBVYA7tH6JvFC2c9J1Uos="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.9_1531234085526_0.5109143017566415"},"_hasShrinkwrap":false},"0.6.25":{"name":"teambition-sdk","version":"0.6.25","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"5","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^9.6.6","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","atob":"^2.1.1","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"5","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^6.0.0","tslib":"^1.9.0","tslint":"^5.9.1","typescript":"^2.8.3","whatwg-fetch":"^2.0.0"},"gitHead":"90ad215627e2a542222a8174c43b283d4eeb602d","_id":"teambition-sdk@0.6.25","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-kOa8Z602Tqrx0INV5tpf+k1w+suHHHUUTiqwl2E+mQXivi57ZF/JkK65EKiO+0G+1McVP4/koo8NpOnQD6mUMg==","shasum":"1e5a3ec5716efdb699fb6f9330309f634dbe4f11","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.25.tgz","fileCount":1217,"unpackedSize":4563158,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbRX93CRA9TVsSAnZWagAA8akP/1aoWR6gm4nMiDK9qbzf\nGeGyYcvd9nkTSu5eV8U5YoT30FoaevrpqRSAq9Wgr8oulvCRmj6awRXngxI/\nyKwzW/8bgLsQ9jedKIqweX/TovaUlNxblaSUi9DhFBDHYPE5eMkBOZfGQCiQ\nzubYJdn2kF02PT43AMEN5q5lW4llTn8a2Xawi62VPgoG112V0oaCU8G8KFZ/\nPev/+KazXAFQk3K7QNe76wWfCpQT25p87zd9BGxzvx3g9smfqQNnxvpSTU9e\nzH8rYRgvMOUCgXjwcsyAFlFVdX6O9uKOL86STEgTGzo29HcXdBASEW+k9cZl\n1CWWbsXCOli7MSrK0XygrHxCCFYelTqx2Xz4IqqpAV8nbAghmCYog5nS2fEb\nlnRu4aZh+a94kAfba5FnUniJiP3/YO+3C4KzPM1mH348pj2vprSd72ODpWBi\n8jVWWSxMX63FDXV30pKNteXAr1nA6okZtL7BjnIUS5Xij/gaeHIKF+vvU2hq\nNvw/amVavLbjPTKCL4Shr4NhJDha6h2AXwZ+exfKA+IBrZfH/pyWpKas/xOF\n/XZ8odDfAzHFV/sd83fGrhXZ3qFDyYRBXcg9nNeVMisgOANizQdfYMe6DwtK\nZDxh5PO2skFMCD1mX8Tn5giJcB6DoQWVA/qn+kpB+w5vRx4gdOVQUHJigXSZ\nfUGh\r\n=jU9f\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAngX406Gs2sRPJV2pS/S3hrRIiYBglzSkjvEQ+6cigKAiEA89NldTFl0VHT7mEgnSWotLUVeXBoYUTLjQLQNV5iOMM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.25_1531281271630_0.7030693606168505"},"_hasShrinkwrap":false},"0.12.10-alpha.0-cgrp":{"name":"teambition-sdk","version":"0.12.10-alpha.0-cgrp","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.10-alpha.0-cgrp","_npmVersion":"6.1.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-FFTykC1lBWGUl/NX+tnDh31ei7ceOjJYPlqCCcG8MtqeKEALcsTJomZTJPFRmdzdqvwsxGZntp58vysEVZoF/g==","shasum":"522d4e362c5cd17a5e756e3e30773de79ab83a42","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.10-alpha.0-cgrp.tgz","fileCount":362,"unpackedSize":725534,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbRdrDCRA9TVsSAnZWagAA5AkP/03FMTB7pnCKga/oczqr\n75edUfsmkDgkoydXAqX1sDFDoPJZlBJEFVSLKxCQLJzof08pKG/I9HrxqgqK\n/Ei95TOTzGox+n36YZvXPKXdRVY2qUnnLz73KYrSBopC3h3NWRwzLxm+JS6V\nbyYI9MXiCTM8UnfsBb9gB988DR363MJysMVtdcLpuVtnQm+5zKCwmg8ZzDko\nH7DBgbq+I0Edk+cyh544wgvj2Tztwvrd4nEjwQkMemhQNkhwydjW9QghVPtP\n58+/D5fEbYxeYxUk0aKVQhbCci80EC96NY1vYO1fsZyFttABb9uH/TOrfJ8f\nqnhOImHwF55+4G4vtnj4B2pn1lb3C1vk43Jd4Q90wqdtf1OxfzgBq80LWjHw\nDssNgAJJK2DpEJ8ot6FspuLekUsG/1hgbuwoK+ydGC8gY4PHngQP7ScNkeqH\nj6KnrtMVa/6lD7otL7JM520AeZAU2kLD0VvnR7BGugg99PHvi2pIsmoDijeb\nbX3hbsRinfHSRHzrJdY0ONGodZirxGqeQuHkztFEqri/QqJQAyvI3XRDfSD1\n8y/R7YR82C+m7UhSwuCol1ypPrdaHG2pI9Gu/Ei4lh1BZbXa4HN0knOywc4g\nrEbe5AfLzB13jRDv8sdgCMLVHTVFAN9iuo6bdpIN9Lv6rNWbohU7bYSOVPfx\n5dOU\r\n=YULm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDp1McguGYPNeLt2BaVwx4b4avOK3+Uwr0VP5uqVfSD8wIhAP+Bli2Z76Dbx9J7Qz8CGALGZo/HuAFHOVmuCbSyC2V2"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.10-alpha.0-cgrp_1531304643295_0.1389658026941636"},"_hasShrinkwrap":false},"0.12.10-alpha.1-cfworks":{"name":"teambition-sdk","version":"0.12.10-alpha.1-cfworks","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.10-alpha.1-cfworks","_shasum":"dd78341ecfc51ed577f2fa2675938cf4f7e2f631","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"dd78341ecfc51ed577f2fa2675938cf4f7e2f631","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.10-alpha.1-cfworks.tgz","fileCount":359,"unpackedSize":721348,"integrity":"sha512-orjb/6PZ6Tphvd0WU7/1lWyWVMiICpiQulsWkGPnl6K2QWsk0/tE580O16UgCtXAbsDL64/dJ/kc37WPhMcgNw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDyeMUfVeipgGjUVtOy+M7koXA42xA9638fy+gzQzKcCwIgaGTYW1EcyGRyQEiXHu6OVicpB0l8D0c6bWW2cAFONhE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.10-alpha.1-cfworks_1531725542752_0.353826008577073"},"_hasShrinkwrap":false},"0.12.10-alpha.2-pjtmpl":{"name":"teambition-sdk","version":"0.12.10-alpha.2-pjtmpl","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.10-alpha.2-pjtmpl","_shasum":"3c9c701dc976252fccf5b3992890049e7eae22c9","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"3c9c701dc976252fccf5b3992890049e7eae22c9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.10-alpha.2-pjtmpl.tgz","fileCount":362,"unpackedSize":722364,"integrity":"sha512-oL8rcMOOQCGesahR0v/8E2ZcuGBPYMyDVm0PTx5mAcJYV4oZlDtI3qwd+inPLJK/mbuQhqMlKwQuVrUsZTFIhQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDhrGG0KJ5J6/orDYAqfm9mPUqruW9YC9yolWHZeYWZOgIhAMdVLXM6g0P3hWemt1sfebrMRXyM04dtRuuJA++iwITE"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.10-alpha.2-pjtmpl_1531809936646_0.7943291075954653"},"_hasShrinkwrap":false},"0.12.10-alpha.3-cfwork":{"name":"teambition-sdk","version":"0.12.10-alpha.3-cfwork","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.10-alpha.3-cfwork","_shasum":"8733620589696a790420e497a3a6e1a237e38a05","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"8733620589696a790420e497a3a6e1a237e38a05","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.10-alpha.3-cfwork.tgz","fileCount":365,"unpackedSize":727190,"integrity":"sha512-U6adIJJL/oe68wZpATDFXhdAtzYUVvhzYZ3YOtaTSOF2hVrvfmnVMVBK/yBWBQASA78RrTYqbk3/TQrXJW2Nuw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF9KcS4gBGxuAPGGeQ5bpPy2Keqthl761SPcBxlpH8YoAiEA8rsluGCTBI4aEVTwb7sraX4a9uCNbDQrO4vltscRktQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.10-alpha.3-cfwork_1531812559999_0.6725959351451012"},"_hasShrinkwrap":false},"0.6.26":{"name":"teambition-sdk","version":"0.6.26","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"5","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^9.6.6","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","atob":"^2.1.1","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"5","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^6.0.0","tslib":"^1.9.0","tslint":"^5.9.1","typescript":"^2.8.3","whatwg-fetch":"^2.0.0"},"gitHead":"5945328d24b0d05cb898a389217051652ceb0322","_id":"teambition-sdk@0.6.26","_shasum":"6d25f99a8e0573a42a1c11d28857d5e0716783de","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.14.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"6d25f99a8e0573a42a1c11d28857d5e0716783de","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.26.tgz","fileCount":1217,"unpackedSize":4565619,"integrity":"sha512-A/+24areXC6uN4UXTyT7lfFgB5VAquc9+JyffEBA0O9ODqlQR2z7Sot02PvlmCVx3ucKPTOdFLk6mcoPrz/qhA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCJVG0p6ofXIwTXhcvq2Nf52EvQcM1cr0owJKQLOLnqLwIgPF3aFiJnNx0XssFZPb4bG2mtBz6oFFdI7RSwOT5qJV4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.26_1531887274465_0.2780340293805905"},"_hasShrinkwrap":false},"0.12.10":{"name":"teambition-sdk","version":"0.12.10","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.10","_shasum":"bbb9b9480cdabc14a0dd4d011c4ae1f41b5ee08d","_from":"dist/cjs","_resolved":"file:dist/cjs","_npmVersion":"3.10.10","_nodeVersion":"6.14.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"bbb9b9480cdabc14a0dd4d011c4ae1f41b5ee08d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.10.tgz","fileCount":365,"unpackedSize":727175,"integrity":"sha512-oLKiT/EGuy+aSjjIWdqI+fb9gZf17GUwaW+ve3bKrSI9n9jDg5gkoFlBpGHgrOWFu8kUNVHFVa+GLuBaJ1CJmw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIERFk54tKlnNQk0B2Rw16fSL3G+CnyUoRMrQhXhBJsFCAiEA59SJF/Ogbj9a4rXdrtjBOwe9n1lEXB4WVxyO0NrP3zw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.10_1531899284515_0.818671878603773"},"_hasShrinkwrap":false},"0.6.27":{"name":"teambition-sdk","version":"0.6.27","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"files":["dist/**"],"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"5","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^9.6.6","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","atob":"^2.1.1","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"5","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^6.0.0","tslib":"^1.9.0","tslint":"^5.9.1","typescript":"^2.8.3","whatwg-fetch":"^2.0.0"},"gitHead":"0216335679447f9b0e033cfa4d7793c7b61a6b9c","_id":"teambition-sdk@0.6.27","_shasum":"5f6951e46de28f6d3706477e113d5b658c00c931","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.14.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"shasum":"5f6951e46de28f6d3706477e113d5b658c00c931","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.27.tgz","fileCount":1217,"unpackedSize":4565608,"integrity":"sha512-O4qD2FJCQqDxfgUa0eYy6k7xd2eq8LwCg/fv+CII3RjSnWwZRosSQwlWJUuq7WqepZT6QC72F/zZqgYOKUBZ+g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICXTLN/gKHDsEXUHpHqAktMbWLOdcoZh1ubYc7LPSDSRAiB6y6pBIzEQ6GUw6loF/cYf+ToG2m5ttBpfDgEJxyVsqQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.27_1532054704414_0.6872781664731413"},"_hasShrinkwrap":false},"0.12.11-alpha.0-tfs":{"name":"teambition-sdk","version":"0.12.11-alpha.0-tfs","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.11-alpha.0-tfs","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ttME2mLptzCbUYSgWA1C4kj/BhKzsf3z+a6lR802Dyi04qEVTv+9Hv2OF0cQwxs3MSaq3KMoy4W2X3n3fS9VtQ==","shasum":"b9eb8e443eb5a69f6386f28a4d86499cdd90fef6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.11-alpha.0-tfs.tgz","fileCount":365,"unpackedSize":728204,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbWDGDCRA9TVsSAnZWagAAWMIP/RFRNUBy7oRgn/oiIr7B\n2yBaA6w4dyjsnoQtxT/fQwy6+izRuwcjpR0IOvbDpPUqODcScC0geXEhSeSP\njpSaFbbhaEcsJZd41zSh3RcwFBca1VhJo8M8/uf8/1wE5Ipesdc72yCqwY2I\n8jhnGaKrHzBWrvdKo50GHfewh4A0KpB4CepfsSCYLkuJ8s3t55RaJT9S62FY\nkKdfIujn+5dG8zNwVjZGvaB8C/rR/DJwsdX2+9cAKImsDsTxtwcyOfn2k73c\nL9vA+FTyFeMmEFR8c0mnhn4wiIO2K1VMvI4qOl4cUXN4Fstw7PaMf6zficR+\nl9x+GXq7GJA0BJ54mQAC3BN+ftKOFH/xgiUGLxNyI49diAKDKlwoIsI0DfIp\ntNkgm7/4djZ7B23rFV2UhRISkco0Hj5uOqpm3+sFr18or3XPkWJjaANYS1dl\ngLBGhNXUtTJCHrEHdnh1cRIiTAhDoPqlZN/v6l4JFxf1iN8m8RfwkXFjsHTz\nq64ZXykG3M66vTpwFr//cts18gD7eC6Y0d5zqAqqyd+9aUQTGK8dtzD6Gzqv\nY5djGRI+GAjMoqX35/JOnx2Glds2BpJp+9WHosMuauCPTcunApr5yAhIYZR+\nQLx4KA+9XTCc9hqR/wqSeGLoNavuFPN8zkVvW7Pbu3HCoz+Hhid9Cgd41mvf\nysz3\r\n=Cb4r\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDbi2qKtKkDGCb8wBiJyLmvFOrc/Zf2fRwr2bcGqFUQngIgD5u+m0WoVGxx0EsAClnqrHk99Cz0FTPdThXVdGzP7UI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.11-alpha.0-tfs_1532506499101_0.8928670982022766"},"_hasShrinkwrap":false},"0.12.11-alpha.1-rid":{"name":"teambition-sdk","version":"0.12.11-alpha.1-rid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.11-alpha.1-rid","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-1rcj2aRSHfkrrCWtbW31c9Y+v0KhpRMbr1XjaTejz88nqvrmvGFR71xyQQ5oG/IYq9+4qJcPT83XWysntQbdlw==","shasum":"85ab7932826a4ca5df2069c1483a4647f4e0a094","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.11-alpha.1-rid.tgz","fileCount":365,"unpackedSize":728915,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbX9cbCRA9TVsSAnZWagAAMT0P/3av0QRi56jTe+/gTqcL\n38rBKTd+/6TrPZwew5rsPcxFu/2rivEO2+hbWYusq0Wn57w4+ebWovTtP6ec\nhZtdQND+0c5Vk9PNhtsR24/vKcNnOgLERKwwnBIRk0uuk3PsXFkO0q5GXlab\nxwJuAB3ij+nWZ4N8GWCP+B/r1GHl6Yz6nIJDXx8pSzkfw5YDahcZeqwbG6pq\nFqDmGUAy5sxnGobdnmAWBIrAmSJrBAeI1zoTwMDIsoIKsS8lzhXzfGb5uy4T\n6YyNCDgaZphdRDQ0V3iJIiNNp0mJgSNKaFJzNlb5wfu5Py15keSu3cayLr/E\nBXqy/dsR0GS2aC92dEq8c3dg8m+oROF7djHFuwr4HK5P1R5JK41UgN6wG7sS\nqr+sAXhpv88hQlRVPVRmeJpLo89TYxYJfgaCP/CZfCEwJ8t5Y2GUACpzaF+R\nHlDVABwm/EKPNIvq6rwqzgWiF/V5lm8ay7itBZTKHbYFYt4EAhAAS6f7VI5C\nHCJexs41brYUqqP7Nzb4CYSZbuSZHAGqxflMUcd0M3uD6HT0hkQbnoRWSVRE\nrPgztViZgGdRDJGv4YzPIc571ixAiQMJ+V7O+EnJjMEnQhYQgQl0Nm8Qvjb0\nXyacAHEhd9oBCzIU4I6O9xgT7T0ZSvM3xeeyQGXec0wlH3qh+a9Wwe0lv6u/\n1PqH\r\n=W2Iu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDGQ5oF23uxbOzlfUTmJ/DI80/PdHHgTTTY5WtSNWbUsgIhAIOt08U2ZGrsMceNto+3GvBGv3egYk7SFR+PAXbVwpp2"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.11-alpha.1-rid_1533007642647_0.4773469459172961"},"_hasShrinkwrap":false},"0.12.11-alpha.2-ridall":{"name":"teambition-sdk","version":"0.12.11-alpha.2-ridall","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.11-alpha.2-ridall","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-zuvLZyznO51phGEvf12tGSyWYQPyhCY/1OHddOf3sNxmvabvStt8ZCCJXmw80OJ9mUhFNz9f+R0ylVsybf3Pyw==","shasum":"5142ef7c63afbd34203c56df9210dcd49f370efa","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.11-alpha.2-ridall.tgz","fileCount":365,"unpackedSize":730093,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbYBFuCRA9TVsSAnZWagAAggUP/iuX7ZxqsRMgubXbi7Gi\nR1JPb607HF9YQCkz+Tia8HnQmsCZj6v0qMhL+57i6/50ROCHiv3RkacdqXNm\nTOBlWD8e6xRbrvwoPVRuneQbgdeZTkPrzqhAyBk+p8/EiMhvACJYuFHPAc9r\nApf2QjeaOrlfElZjdjPlfz7ySNB3DgkuuoSZ8nF+a7Lo/TpjZCUE1A7ZbR7X\n3LBhQOwxWnA+fHy+i3u10YfsLZ/V7C6LTokNR5j5iC6QJBqWj50+uz+MjLY7\n4SYqkQ1oTgBvp/xBQUdfYe8efBDtQZtIX5LP8twkXi9hps1xFTO73fuDy1mk\naGKFqKdRwoNHQ/PconYkN09vUBxXO680KeejCVj0XalbP2zVQKeVW91hBjxu\n238KeR9GL84hd8THhTYwL9zV1hK7ao87o55m2kBitnd5KL2vQW771wi0fJ8+\nBLYAlyU3VQrvle2oNnMRT/jUjo6KttbdMyT/cXXzl/a7XraIlfo2d/DPIzsT\nhIuXTweuKAeLLMde1bvVzwJddjY8p1v1tNSGBIVjGj8GhYcaBaBMjZ1avtp1\neFO4SBHs8In/UUQbtnfpzYmalrdaIDPmKM6sCgpijXvCLWW4KuPfSYWPKu2y\n05vvs5CpIqMiDvprceDu6yRKcVHn4qLIPit9PrzHGP82LQBCjMHOSeJB7dgy\nByJe\r\n=hyTn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICTIt+w3CLUGZAuEQLKAlRx1WyguuPGkmAuLzExGRnPUAiEA598U4Ef/w4/Nu8DPVHooPZve6G8awfFM3FNGrTgnB1k="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.11-alpha.2-ridall_1533022574128_0.9310224023161602"},"_hasShrinkwrap":false},"0.12.11-alpha.3-ridheaders":{"name":"teambition-sdk","version":"0.12.11-alpha.3-ridheaders","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.11-alpha.3-ridheaders","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-nNEJtBJ9QH6E6+GbJ50yC9NBqVg9pp/Pic34Y+14v89BCqZeydNIuS9KdXtLOjADeg3B1D9DpfVxCBcBvyeAvw==","shasum":"fcacf4851eaf74cdbab730fb2eb0918baaed8931","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.11-alpha.3-ridheaders.tgz","fileCount":365,"unpackedSize":730644,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbYSWMCRA9TVsSAnZWagAAffwP/2X3LgrJbJ0pe/rwR5mu\ne7XeXDEnkX/jjHwVMHbYsB2SeVb4hayGAVMvsRt1yYp7PV+Vn54mImAO1yKJ\nXrBDu7YSirZGqZOfxxBYZ9WFoBrGOkLcF5e70dZPKKjKN1YRPsDs6yyd+eGY\nzEGiOPY93GJQDtq1B5Gh5fNbl5eFJNipjOujnGmepAc/vAlmHDBp/N2y8yuU\nbcWJZKF7+8pkZE9GpJgy6l0jW8ZCJbs1zIBevkkCOtxSRrxtlV64ofp92Drt\n3u3H8k7Gpysz2szu7CiZ3gFIcAw7suPiYUHrJT2C2ZknsQ9VyYQ4OCy6SWuZ\nY5fPVtYx0xFbaql4/EhR28saDYwrtbFEZdmAffS/baWa53WFY3qWXaxfQzfa\n8gLHrjdH39Us9rsXB5nbyrG2vjp5GBDF+xXZAhTILf+4UC0MItFoRDNXZshn\nW+bSttuVmUbbsZpRVfiWkdDL5sNO9DzUMXW3FVwgfNz8cPe5Ugu/CDzMYnfm\neCP+uDFbYw8k1Cc/NLBeTYy/hwxPx1HwRb3MuZWvLSNjVmBYpJu6WTj6xSwT\nW44h3difdkdcnJEnST47XQQKlhAzr+7+A56iPdxibGRd5KmeeKle4fcve4W8\nvCSBGSfSMqFmXQIXVycpJRpVH2qr6jlHvTIproILAEyowmxcSGRmgDC4wvPj\nQTjq\r\n=S7kz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEK9oR/XHI9kjhOSyx0e+8zL0xpydxCsM1JA090T6aZSAiEAmoPw9QZpYbETfpkR4jRGMqTUclU/ZTgBmMEWlTtZfP4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.11-alpha.3-ridheaders_1533093259456_0.3414760774160164"},"_hasShrinkwrap":false},"0.12.11-alpha.4-ridready":{"name":"teambition-sdk","version":"0.12.11-alpha.4-ridready","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.11-alpha.4-ridready","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-oXCUpGUW062b+ZdWsH2i0IcO0e/SWLKkpN7xz1FTSv99R/FIg9yVhipiCob4qh+ySWsS35/OHmPX7+5619pKVA==","shasum":"feeddd8f93238150824e2173307adeb6f77c9183","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.11-alpha.4-ridready.tgz","fileCount":365,"unpackedSize":731963,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbYYUOCRA9TVsSAnZWagAAZcgP/A7ImZ07icIKiA/qAnCO\nF9GmKyd2WNVvAh1Dr8X4zP/ZioVmi6o43OvlKE1WYA6NMlCrJJtAIxb3P51g\nhxHXd8i6MjAKOMayQAO35j2NBFxGcpvt+KI9CpiPLqikpbt5jiWPvM+j+z1e\nr1g066VYSl5z7Y76tb2yExIYY3FLbDELsg5R3v4uWlpyqljyFV8V1+QfHI1S\nWGoGcbRS5C69y1sMmE+V8aNejFBGc9AIBxbVfF9igiOpsTVRfgqcfc3hOdVc\n870ThuVOAIusmQYGpuTBx8N39D7hDfceC0h+KJ9LVYDCjk/raRre7NVGN9Lh\nNFO0fDT7AmKGm4rcM0gsq7QJ9Q1w8NVW9QLCQZkfV8OY6dUmExQ15HaGhj4A\nq7Z49CigfF2W5fNy42DYMpJokk0m7Rxv0MiJGpB5pVuFNtDFqf0udCAr9u4i\n1FRCvfvToNU+3zYV73DVMMB3WFv+pbIUSHvIvLCZ4dDwLb6aA+riN9NW9xRS\nwUstDjYU8bNlnA/m6Mu7GseqtRHohYdjVdr2kW0hBC04LNQvzfW57Vs9NV9P\n5afLCenRbv6G3wpTwVgPn8EGKuaePV2fV+lucfz/t9Zth3mmhGtUPAT3Imfq\nw9+32Hm/K32u0rwygtPDLanH570+f2oyWgwV7AH7ykafrXOmMBX9W43r4ytp\nxLsx\r\n=0rsH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH7W6yCj6fqrAcv6T1d1esQi/nNiLmWICa5EYcrft8S0AiEAjlkCoLYfvARjeMOHGYqYjLmuCe8c+lJyoNMd5XSUmb8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.11-alpha.4-ridready_1533117709646_0.39526204603083737"},"_hasShrinkwrap":false},"0.12.11-alpha.5-rid":{"name":"teambition-sdk","version":"0.12.11-alpha.5-rid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.11-alpha.5-rid","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-TnNljl40DGGcTl4CwucghYPmLeJT8Hr099G3Sg3ur1RyPyHmprydM61pfUONpcecaNQyoirS6YYq8LooFTXw6Q==","shasum":"72c300cb00cc579f0b9b65c500411842714f1f85","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.11-alpha.5-rid.tgz","fileCount":365,"unpackedSize":732004,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbYYdcCRA9TVsSAnZWagAABfQP/jzdCsUOiIZUfC08yokb\nstE1VMzu56+QLwuzbSKumKHDMbXbvUA34+1o1bBebgOaY8DmJ/L8OkX+3rTT\nW/45obbLrxdCqED+HMJMiaqxd5Dbm1gZlVF18XWEXhqIsvU5asyIOo4EljrX\nZVXlF1xpcub4A5fHO0d3gW5AH2pPINxvhPf4KJaR0ZCnVQS8DINOBgZwER3P\nqe5aU8+n/1dgYrBI+ei5rXHDHkWBnC8hilYy8gNnYJxPYtSCUEXNulh+RjXf\npLPqEQtm+Ef0h0Wd5tgWNbZWV83GqoBc8B5wYZzfNZnmiQlYz5cQ2PTW13O2\nfj9Rajp/ZkU+mvGoMe3uYDgeQyQc9W5ojeRTtm1Qj7b7jUWxpg7USoae5svv\nU9l2kU/94cSxEZhoS3O+OGyOOgWAVJ9fsAoLgBWPkYQv103+6c3uIkyKPWCH\ni/hWvFpJmXR5qp3pr15vFD4WmE5vtg8b75ZHNgvANnCiwurq5i6grD9bG+Ch\noDzAsnYLeAck401vtfoN2eXGSt65dtshiLHyixD4MKbN5wUM7PA0/KUPhzwS\nrTjnTE/KGLj00ipmQP9h+JFQ+Lo+QjSbYdUoNYbLBDXxAZhbeMempNNZlv6f\nVpRLJcw4LJ1etl0PE+slv9QaugTl0mUDYbvE3R6jdoYNxMjoC2KlJIPGRIvg\nLU+1\r\n=rsnl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDmqfgtC5Vt5CqXI6Z7OzLcx08StGJBCr6PPa+72HMr5wIhAKfuQY1x6CB0ROdmAQt9epqZE0XX3p4yRKO5pTBgOE8O"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.11-alpha.5-rid_1533118298750_0.04400713498239761"},"_hasShrinkwrap":false},"0.12.11-alpha.6-psa":{"name":"teambition-sdk","version":"0.12.11-alpha.6-psa","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.11-alpha.6-psa","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-TrVGt4M2gNfH9ClBVlvt5NGbEgMsBJm0MV5t8SxCi4h6XLJfXQ1nM8kzaaQp1/iIMruXUwdptjbIeHsb1fOYZQ==","shasum":"77aca0b09c524ea80a506a926b66386960620aa7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.11-alpha.6-psa.tgz","fileCount":365,"unpackedSize":727408,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbZ6ZZCRA9TVsSAnZWagAAGocP/AmobNE0WMKlwal75St7\nZjfLWDxaOry8JweKJUwTVFTKLkS20PRf/RZKPbTcQC91J5fB1mK/CDQi2mb0\nlFDjoiNjNl27A1xerVRSkBUI1W03tow1YICrWPfg0vQ3P3Cvt3ZQ3lvNBQY4\n4z3IyMYhBUk6RRCo7RewAxfBx9i7dk/GtQ0HuXmVPgz8g7kOzhQ78J+Pa6qA\nCtU21B3I9++wFbm2ekqbQWkXLhYbhGAxa/DZAAT7Q1rz2c5fglSmNL1K6QLv\noiROvUCcaPdrh0d9xI6z1TBBgy9MaERJoWeX2dK2Nr9KqbpFsKmwTeoHfqrB\nWcnazbePcxuNwPJn8kuD29vHyb9DiIzvaNKcRAS3JL8WUk0XIyCg81Csjpe2\nk2wrFHUO0ocWG5xTbUHUUgFTXnIVhW/NQ/stje0FYKyU0hB+z030qVji8E+J\ngmCA5V4E1obSUj3KPPsPesRxVuXreI91rwuUgjKfxDykqvF/NCM0+SUX20t/\nnqgt8l8H+u8iRpozttnLYS6rkoZ6qYe3NXYNZ6yc17gTkxgClduLh2FSRGVY\nhxQbn6ExfbTCGn5AYfW5L1FJYIyIOAopFlY8AH4sfeYDfLgI0dHx3QOIv9jt\nL6O9OVg5ytUgOyarZP57oWdp6zi1kCi46FqDUWCB64bOjik+TfMGJqRRUabK\n/3if\r\n=6vCg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE94Rk+eYBJsMG3GUsUn/UUs3ZRyjqMp/wQQRyb0w0+0AiEA4CUlb61gK3R+McA50ZXe8FrJfCCc35ULfp/A0VKWzTc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.11-alpha.6-psa_1533519448460_0.7181154717031191"},"_hasShrinkwrap":false},"0.12.11-alpha.7-rid":{"name":"teambition-sdk","version":"0.12.11-alpha.7-rid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.11-alpha.7-rid","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-Zd4HaPiOdjhPxMdI9Irs5KdRVxJTuD4axA6a1PzBCi5b2Kw38piwuVsyeVMOzSSFRzamMasZq2oiCgzK1fd7Cw==","shasum":"6f52476e0505229d1336f275f023047922549daa","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.11-alpha.7-rid.tgz","fileCount":365,"unpackedSize":732281,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbaA3ECRA9TVsSAnZWagAAI9QP/3iNimY5fpMYKm5iDt3r\ndCe4KH1i6bmCyPCbEi78GG+15D8xCNXB29SmOvPCoTDwn6FSNut/O2lJtCpY\npqv01ip+nzEgVmh1UIcjHrs9sGNp8oLOEVIPP1XPCbFHxfiaoBDKR8W7iYFa\nM0C7I6b7rS/BcLPLQQ8vhRkfXi6R3BhzMlynb3PjLnw8ENCMXFB9F0IC1pnS\nmos5bTKqR2+Tqaeq7bQsjhLCCBGtbvsfZnx9V2EypJlRAfI/hz3eXAwZ/SEi\nf7hDh6Q1AYhZmqGM7drK5L+QHv4q7A9KrrMjaUc1QIQCcNipBbiIoh39PFlt\n1DaCeQLS1b4H32B24syLCHgvXxIgEn+uXWwcahQptCeGtprfOFH9bJIZelZe\nY1JGqou00MudNVPeIN+uYxIFamht+YjqTzQ6TyTJzBEXvGKStfgYS7l3E4oF\nJ15LH7NjL85ypSQc1S9jgNtY1N9oq4UaAwH1mhBbj2IE10z9rA+WiQbqdHwM\naQiKoMZa9DEuHXQgsGvlnFtYMaS2rizFqZJI6HfHOeaMI9ve9vR/hK2lXjlk\nAqHG8OtNf4PYfyBLimtSNzBAJkOrOgWLzsHHoj3C4wJ9Klu9xnu2XvDSbDkp\nk/Jh5OQF1mZJC5WINQ9vo+l0HShQlvAa2OaLwpI/27pjdp5u+LMva8etKJKP\n6FPU\r\n=NGil\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF9zy/aMwaZco1KCTfjxIHbWKtUXcmh3omPGbPB6KwP3AiB+i08S2znAf753IKa1pOs66c0cT7D7F7h3DN6M136hCw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.11-alpha.7-rid_1533545924169_0.6876009037754469"},"_hasShrinkwrap":false},"0.12.11-alpha.8-rid":{"name":"teambition-sdk","version":"0.12.11-alpha.8-rid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.11-alpha.8-rid","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-g8uIPTfpVUA/LVpbMxtt8uMlQp8MjRTTzr9UcLmtgo5N/4CQ+QmBIi5QxTE+PTW82aSw5bnP4DTHzdnXC1977A==","shasum":"73f32722d0f8f0f00ae159eeeb95f224da7e3856","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.11-alpha.8-rid.tgz","fileCount":365,"unpackedSize":732525,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbaBJCCRA9TVsSAnZWagAA3XAQAJKnCbtBpCwoeT0jKvK4\neQq3xxouf3P4F4Cmstb/LN4fTDlsL9e1Yw9f0xnYleP18A84Eb4yxF6Wx1o/\n4GudNfkwqKagvChdfJkIucOScrqXaZtr95c6kwxwaL+83tsEMzsSNMTHX8G8\nw/r/oPY+D+K+gVtkdaBZfi6nYO9Kw29ifLEJ0zDFmWSZGcEHPpRkr00zUs/z\nGD+DJvNMManRiZaU5tanyLdTIVh2emIgfYjx+yzCw+eShKNhqhipSo4u+v7x\noL3th90biMrwJbuwXFm9AR4qKbOEMzU3GzauMExVV63uJ+d6lAx8DE/TU4ic\n9M3WsuuKMTiAyJRPYS/iu+uzZD9TBYteT6b/Io1Pnwiz2F4I0aci5USq/oK0\nzcVZGhMzitLzCY6kTcJxAroz/lnopcplXzFhUuAifB3awNFFXRGk7V6dueSm\nH0Wql+aAJKIbQtzxWE0vHWUb5LO4QEFfIHdczu5nNx22QSdM/KJbHzwnYS8U\nz+Z1hOpJ6n9YI6bpEUukixA0stH1Nod26bYoV+59UdFx7OFCZUMM9HWJI87I\nFGIFETqOPbHueblsUxtQsVaXJERfieI5/rmRaG0u82tUlF8wt2NCGsU9AQVm\nCSpbgZUZFatFkuMsqov7RZ2A9nVBa/s3rglRxp8euERpOswqP8mO2WUE+bJC\nlmqD\r\n=IvAa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICo3AD2q+MVoA7S+2eNeXBwxA+FIXx7Tq1tEiuGccbHkAiEA86oQYQF+o3/Yyg+OQItJSHRNWwkYaDmjNlFt/pRt6Pw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.11-alpha.8-rid_1533547074079_0.8586454742832468"},"_hasShrinkwrap":false},"0.12.11-alpha.9-multireminder":{"name":"teambition-sdk","version":"0.12.11-alpha.9-multireminder","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.11-alpha.9-multireminder","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-GN7ixtXuzT4XtikWcgwBwwFbsXC9qDMLucvIF2fMx2DeUMuu1PWvvMdA74nDb0TOmk91ZTz1VBgcpTVebAgsVg==","shasum":"051bf40b932aabc458b162e0ebddeef0a1ddee0f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.11-alpha.9-multireminder.tgz","fileCount":365,"unpackedSize":729010,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbaCjkCRA9TVsSAnZWagAAkkEP/1Dt72kXTO30rmS6Ckat\nprjp8hUo0CEciD3tXqP/7nFkPUVhhw4WZSHNAedHz8i3AzNXUqvJJ8htMyKe\nEeI+w1UZx0YoBO95ZuL6LyrAprkG9afv5+LfTyoLIQJ85JBAPZcLNn4KcjuY\nGdS//MZS8l5nMDUERI/Usg7aYNQn1wyMtV9P+oU3F2W/pA1LEB6O4zQkbQvZ\nDgFftXWWfSNR89Vcz2gceo6pxaEJm8rR+Ab5x9MUuyjuerBNNdtoPfIiqr/u\n0fg7yOmAK+twWnfZ8uyWnTtIjQCQqy4QXn98sEzG/WSvNzwRbfxL3NMPNgAc\n8rrCh94aL0OsRiV6L6ILU5KoHY/znsuUYOAQEOE5oqrOpjA6cY0Re09kcxUc\nHB/krQ4wIWc6+/Rd9mQlyflhPo5+1NABaXlESJlrm7vV041fnfw1Bqot9oiW\nDPto+f+mPxQJh1NxdsrnbGMEM0rqt/tdF/Ijea+7aRze6EupCFBVQwubftPk\n3/fe8kzB5k2Fq0Fo0ocpOo8DTmqV3o65D42SdH3i3ggUIE8IO75X612ln1zP\n1cHvaIjSBDdVlJtHtkKmVO+wYI/wUzEfbynne1SCOF/PUCFhfJ9bdHzaMmtx\nnilsuaCzUDcTq6iDRp0M4n1f7DcIlLfcVEkaqdwtesc6ty8Ej45pudOjEemK\nsV7A\r\n=wrYh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEMzfnjmzntvBFvTYvKWKe1btVnhK/kmqsckZqsMwNVWAiAByVZ0R0NZiH4RJy3bbL0b4dfg/8lsFMAbYEJbA08Oqw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.11-alpha.9-multireminder_1533552868457_0.47641356020429737"},"_hasShrinkwrap":false},"0.12.11":{"name":"teambition-sdk","version":"0.12.11","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.11","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-rqzcEStVa8jjgqiTbjEP0r+kT4iLOHGVOZjU6v9CxY7VbxJ4mv589i13Bcwln8f0C46H/HwwHnKUDziDSngCdw==","shasum":"e630c1da885c47de616c527b4312cb2922074db3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.11.tgz","fileCount":365,"unpackedSize":727377,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbaQjJCRA9TVsSAnZWagAAEIUP/1DY/BN+7Ax8ibJuBLce\n6yuFSyzn+iEWTHGtzRGDJmEy+eIJno3uPc0sANsrUdXk35uvVavKV62Pmuw4\n8JZREFRWPmJCLz8nnytxgGDN1lHayKEj7yp5spCXVke4ivjwoaLAtoaTWi2q\nyFGFXu8YILn4MOrZScBs4GWlTPq1obvBfuhDWXba2dCkuelYTHBMa2mTrPt/\nEgMeRQiXEZ4Qj7z62hke3DNy3rVmi/1yprrCP8c5pKSAM9smFMszWF4DuZCw\n40jPKOhAbxtOagmkSevQNhjEyodvtr10eNiKNvdVWU2CWfZyBbPmn0BBe1wt\ngSi+4BpZGAiB63yTGCJRM/E9JNJEM5+ktwYZ4YcaWyI9B+ghOrhBFsj4vxwq\nyliY2uSVbrgU6T/Q2aZcD8QL5FGFRkMn+8K5NZLJNWBcvUSQ1oSFt6Ze5CWP\nGgbOstOfAusNrvUeo+gDEm43yNh1hKAAE9tccpTKuVgMFJdAyFIgb8WJAVLt\nepPNoSvt8op23xMsS2HZncO6tb/TeGUGkVXyaUxdqdAGmRhLInBWjR6eBh4u\nwqMPGursCx/gT+Aq8fRrwrH35R4+chKkhWEiOecdY8alAJ//vDKDOGLtHh5n\nhbj5eFTrGLVAmyPgG5pUx4LNuWDSn00hsCGKIieWoKPX/mfvxOzkaKu4Ax4z\npX5i\r\n=GmMi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC09f1jIxnxbi+zMQGfQhKf8VT1fZE6xZhkFvttZ4oWrQIhAKSTnPWdTS/go9MbjCzK+/SXfjqSXpjqRWHvajJr0R/O"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.11_1533610184517_0.0585639583022719"},"_hasShrinkwrap":false},"0.12.12-alpha.0-testplan":{"name":"teambition-sdk","version":"0.12.12-alpha.0-testplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3"},"_id":"teambition-sdk@0.12.12-alpha.0-testplan","_npmVersion":"6.3.0","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-XGi6VjZM9DclQMaPtmtxdir4OlvNq4PlmojlmVjSPOuxYOKkx46wIvJx7eM7ldrz3dN2ic1G9f59eR4T//wMLg==","shasum":"0b155a391ea18432057b71355190f300bcdeefcf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.12-alpha.0-testplan.tgz","fileCount":371,"unpackedSize":737139,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbaTPaCRA9TVsSAnZWagAAqOcP/RpWdg6J4Fa0JGE/JWih\nOrNpjYL+eqnYIhFRayHRoojbF13w/MOE55KpHDGnbuWE/EjVxaDqrc5MnLbU\na2rRpKD5SzhgfUaTRocdzRsP5xYGMQg1zyOlCj1VKst96rl9EhCNnh5OQusK\nJfoYNZRC7uFfdYQcDBS6yFCKNkSF7EovwEEvhS7YGhRS1HMfNzhLqQ4EE1B2\nCe6YLVi81sFoabSAVNxiZE7GQRPiTh50zkXbPV7GaEmvVPyl4zWZ8qmkVspD\ntGxfWhD7J8Oc5Q/89NybuXHLi6+Pxg0LKrvLmCSI2wCRoYIJt6r7LiVP1O6o\nRroRkiaxNWx+BbExyxWe/sg+9PdNE9golP1Eh/GiStCL++99awuWmKiiiOCe\nbYx9luomdWhNQS8cflZ6bG/XBouKmmdCwi6o8aw0eM5Qq/i/BiWRq7c6DBK6\nqDnxIcaTBk0GilY+cYKKFaccasIh7MRKngao1c3hsLEZ54RHum3xZLURTjXI\nV3m+G070KXqzYQTGteolDGZl5Aex1pemCtYm9jQM8CKDq+QKYOBVDuLgjh32\nEKhTeY/LlBOBBgfL4XsDpPqUnV6Zj2jt/G5Opi8XxpMn/ZeMn4lJZCUCpYUT\n9SxP1xPXRjlE/3fnri45jVci5CKERHxGeJvVW61km7d+q+g0Hy2FZjkWId1T\nXHcq\r\n=QkQy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEasw3JxVbmfWIs4oA3xj+nypW+pJSEuQJ17/0N/NCw/AiA/lB671dhWRFQtcSjWne1ArEd4zBLCZ3IGZbwKJNFX2Q=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.12-alpha.0-testplan_1533621209844_0.6100562623633412"},"_hasShrinkwrap":false},"0.12.12":{"name":"teambition-sdk","version":"0.12.12","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.12","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-h99P8Ub9fSZTaq43KPla477ebk3WBTN+NYJ1QTTAVjEmsMD2WHcoEFV8y5THGc807fUWMYpS29PwE1gdWtE6Bw==","shasum":"874f3d8a4e2bb28dfc8ede147635ec83c4cc0097","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.12.tgz","fileCount":365,"unpackedSize":735784,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbaq0JCRA9TVsSAnZWagAAKioP/RUyLHrewuI6/tMQPNLv\n0m3EQl+GeLD0Wnehk7Wb8VSdz/QF2LrLpvIBbmgGChQWJ7VGIwbZnIm3w6jh\nhv9wWgwQLQ+yUz/61e+RCf3symcuiV0wSukD7uu9J6XF2XAGMhKmJ0SeTYgZ\nnjasCKqMHZ0T2qxeY860eqJ/XgGUa95/tZwoG20HLn1xMlXnXWEvlHB79H5x\nRqFN37a0Y6vLZstTRx8U9ZU5edKkh06VGV71PvRpjoKFa0uzfqG5cJZYtqgO\nPhMjZ2glFtI+zjIj5a752+UVBVYTC7E7MIIu2H9GeISUAyI5PDI/eaAXAbRK\nIG3nLrsZlXBPo/SgHxV7MUM+nzAW34TLWgDn98W+ZOSkBezwazc1xLFKq41W\n6UB4zNQwF5+0cj2IC9+HFLbFiyiBsgG9vYMLzffwW+pkFxsens3ij1Oks4bd\nItyNxLtCZG1uD8HYx7FskdJ1W106Xw/sVDSZ13Fw9IpqCkazAcLFE6TGMjqy\neCzZSAcJsqsf34Kk73dwFhc3o3G7BtJdO8+i8R5OuI/gmr1OeON8mkJ2LWHd\nAZ7irOzVg0vCqha7t6d8RHcu3dvluBQ4TwnfFOJR+SHlM3qX1SmGo8ppbp/7\nCRLEFbK8WfYYImYiQC7ycKaX3g3PS/RXd2mgYUHFWF0Jbiw/W/cXw3oLRcor\ndbgb\r\n=kCwa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCa/lTs0Yym3Zjnpgp9S/aTrYzIS1LCzuT0EZndI1CgnQIhAJ+N5D8AgMZDTlkt8swvPBFP50S9UrV2bWRjkKrrxjqB"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.12_1533717769446_0.281083491111614"},"_hasShrinkwrap":false},"0.12.13-alpha.0-pagination":{"name":"teambition-sdk","version":"0.12.13-alpha.0-pagination","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.13-alpha.0-pagination","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-7ZxbsPXfAz9quZzh3OYBuq3jxtXDs7QtwKoVZR20YsRrEPcU9D8z3ve14+qKiNYArfqZxnIKCxCGP+lZvoZJcA==","shasum":"f6c390ee1b7be206cc15b86a407e6f68f3a2b187","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.13-alpha.0-pagination.tgz","fileCount":371,"unpackedSize":753808,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJba67DCRA9TVsSAnZWagAAE6AQAJlQ+MYVS3r0vaKd0q7J\nGM2F7QTGpM5nzAHg47SmxQKCuMuuATxos5SnDfCH4DcgkdqEz1oEuDUEy5Zj\nIwAy1SXwpYS6/f9HS21D0mjncfPRw2W17m+kskENOG9qHr1EAmAk7e+LAJf9\nu+2ks+EZZXNkpo8ih0JgYF0EtrvV+wZo7rdIVBqSgHup2nfXlpaef2UmPPSi\nIbPaPISKBLWTdA08Qloc7OC4UCaamNcATN/HCPDbZuTNBsYVJPMuG+qK3SNQ\n9dfmDj8xKqmOl1BgGUgcS1NC+GJPv9jioEMtORi3+ZjCElusEhn8VkzGfADx\nixKbOBESGBi9EmneZw3CGIz6oeCirB8b4wERO6uQnEj6BRsQOewcCxJKOqlO\nddoJkd/Qc5XwPZ2hdr2k89sqo+YM39HWzSAfcldeL3tUrGelsAlTIypTVRtg\nU52ZOEfMfPVhNjaZ8a5hMef0RXDlTql/G8S7wQlNTxjj19jodYoxhjOkFKPv\nsWcW4RsvWdg4s6NjhsF77cHz7BipbmwhoOKTEw15G5+VOLPEKUzNMX0HyjBb\nom6RSCsRlbQt09F3V9caWzgUyuRs8Jfk84rmnEnFdZBpHApV3LOZTlEiYxAa\nkcPplesRuQCeWAXfKcpg3PyO4tzqOJBekf5HrXEeKjHOhVyyhQq//CabPHY7\ntwOs\r\n=GT6P\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC1q4Zn/sigMyFa3pWGrLTeRsgIikRn0dCLpv2u8UTXbgIgTzztDlqxsC51r+gOok7ff/mzCSgythLi6rto0qLi6cg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.13-alpha.0-pagination_1533783746323_0.7764084640813909"},"_hasShrinkwrap":false},"0.12.13":{"name":"teambition-sdk","version":"0.12.13","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.13","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-7MG41/xWzSYplGNNOT//TrztJb6Gkmdu8MvXDcBk7tNvJ0tICSn+xQGz+3Plf8QUEyZ1YxVkdvZUWwIWH83arw==","shasum":"fa6fa32cf0095d96ec1bf8c4f91b27a17fb84bea","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.13.tgz","fileCount":371,"unpackedSize":753789,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJba/Q0CRA9TVsSAnZWagAAqBUP/3YsDqHi7/G8K5h/SIa3\nZ3cq9MJ6KqsO8RwQutBLzYYy8CMixbEpepTyP+GeLwOhi2W7k3B29ArGp6XN\nlE9ewLJpGb8wFvyZVkejJI9CyefF+PdB/ZBAEhKT5SK4pEDJio0xh0h82vjH\n5JfNleYZkyi6olltScZUHJuGP+aE4DlSmX1xggYWgO2zm4FAF99xIJSrPIIN\n8fQlaSNNALkLU8cMz2x9XHIOQlKtrvNY+sXBJA75uXfKLWjPLLZduxKv3Mfm\n8t4VihltflM6IjsIJYsLZiqyXNCwpUMLhd/Uj8LgsNFNZCoGm21612mUOknS\nGseG9ld1ZBGvbY444qw4laSkKRrRn07pMozG1ylYUqjpLyu2CyGxo1+S30QI\ni45RCs+VyoCrthqX4bQBWHQs2O2xDpTpv+UvEgEzYCODl2KJ8X091o9iaMjW\n6hVsxdGBLUldSeNNR4srvDxeFxeO6soQckR9QM2ztXnrf9CUqleVTXph4buL\nftqq4eRJ/wWtHzE9bAJm+thHIDFO6IKCL+2cPAwKEH6uT3C6t91TPbY+CPg6\n63iZmRgrJx/gAu5/y3WFnRM3cylTJZ40wN68deM877zeXEydKBHSuZkdVV8+\nJDLo7wq79xkcNG+Ee2gOXrMmPU8jmmcI7BeHL0GbDtfCVktUwRRFA1jTxKUg\n16zt\r\n=PB16\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCU4HOqBRF0a/lIWAT8SoW8Ns6leKFJzdLBI4aRt19TSwIgPxUzs5+wTkCK4HIhcFEH+9mA7kAK6VgIT1Arw4YCbkg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.13_1533801523689_0.3165169766858249"},"_hasShrinkwrap":false},"0.12.14-alpha.0-testplan":{"name":"teambition-sdk","version":"0.12.14-alpha.0-testplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.14-alpha.0-testplan","_npmVersion":"6.3.0","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-M/DSZ+eFOra4Jixf1G1c1oRoX86mv6j1xfp0IE19OAhQUG58Y0HjZKFQPSkWJDccoJkddG4SNBFedgmiNQ3VSQ==","shasum":"68996dfddd94c21c7157b0c2235cacebf23fca8e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.14-alpha.0-testplan.tgz","fileCount":377,"unpackedSize":764238,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbbAWICRA9TVsSAnZWagAAhxUP+wbY3fkwJg5xBjBFi1m2\n3httlmgerBfKVpEtt5jkRpJzF3cy6NLa4kI93uBkTdMXUX7ZZ4GEcl0QrIG4\nRgL9o2uWBUmMuVezNbjFOSFaEJp5+77QShutZtHcL7Ce0C8/90Y5o+KAPLwn\nspa/7Qr5MavvONat2ix1psOGw7/I3tP/kPsUDTasCXL/Zpw3n0bYexig0MKq\n+p/xWKqOYc9ozj+uAYOGxLXOWwznFF3H0gjOvX/Ru97a5zn9vsqDOyFMFgG2\n5vE1YQEdOTpNBl28nUmwUwq+rzG44PAQeSJBpsnBkbH/Rou/+kkFbS9BRf6f\n//IiKSje/S+/FiSlaut/mby9pm5qhEN8LXTjWF64N41DPlBjpmY5gA7XmzdI\np8frx60WSXTMavaPxogctJG8H3KykWFlueVj84TVOosor4xUjJPiSbc8Fc8f\nWyzKYQGvWr03eCy47O0VgI8lv9TN/T4fej/1QISONOwTKj63DCjMpLZmVr8t\nTxT2YLsUccfV2wl4CyQrNzsW4Zt/kINCNBFFF87r+W4Aw09yRaQc1+O2fEFH\nXNZ1mimaM0sZZ2Giro12EdbcuyPm+VjKZHZjLupdT00vv54HZcbku0r1ph4e\n8tnPoyGh3zNDtCy5hMSix8umAxsKi812Is3tuvGcSLsOwhii+b8QteUWDNEM\nw3gd\r\n=3tJd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFDCrP4svqzkJsU6iNUok3a9ntTT+FpwSyTGx9Ngjb4+AiBSq7cwGuGxQH6knemroX1OHxBpWISnfFADdLjZFCdRLQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.14-alpha.0-testplan_1533805959965_0.03902009432463571"},"_hasShrinkwrap":false},"0.12.14":{"name":"teambition-sdk","version":"0.12.14","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.14","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-g0xP6nWFj+g7B0abXWXDBFdCWX7pP6w4tewjyZHY2GWGk4S6BqIgMD+SB07j9sYdDMDCTr4OzuhRm4xc96nuCA==","shasum":"e1ab8134adfb0fff0441ebeb5cdfdd2f97fa0bd8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.14.tgz","fileCount":371,"unpackedSize":755981,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbbDDFCRA9TVsSAnZWagAA8cAP+QEfzXlS5SKr9cMhy8Tu\n2qGPyIkojpCSDuyE03SVZgA/uukHmHzFUNaGsVG2SaVRLDslLxXUe4QGIVrk\ncWpMsC1/b4I3m9RzWFrtKmt0BDSmjs1y8HEWSl3uRUQEzkDsn5yvWGSS7uDm\nyhHDby/cuCDzhOMMhPahesGcDL1Wa1AfCGHNzLCK5Hqy9yYYBVvmiWFn1rwT\nAq8YCoKqUjRrfmaPmH5aaYcF6puDQ64Pnf7i0nAuJzRQO004ADRT98wJrciG\nEQM+xQEmzgSqj3rFahLW6ceVs+xDxzPb+XsGwBm17QujHGfgtX5gMCyGv2m5\nj0rFEHIFSqsokVpGR6kx5BNchDeky469uMWFp5nIFeXWpaO/tVDpflj27NvO\nPAGx3dcy5eq52WpNlX3BUjv2QACttdPZr1xSVjiIQVoGmf0vMucyTbdP51J+\nrSV+r17FeIkL7/DozAEFwQvwsDtfTNih0HJqdFk3LtkfwEoLihTeVgmwU+ve\ne4K9lDItN7ziQ3tyFgGt+463cEyB4biskaNS8krC/9k0gxFonl8s6V6gvOaj\nlK2QvoyYBaf0fiYxFGm1YUN/u31t11nbZ+xuAHrpnH6+fcc5pxeXQm7n4p5a\nNxMFXcAqndH9Zo40hLMhSiXhTtecqYjF93wB3bKGcnZgeV79QnOI2D58lwGJ\n5Q/+\r\n=FmwT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDKcbD3X5NwAtLob5ITZ19UFO6N5drJn3gxVjwwjuydygIgD7kZum+VosSf0kaWoaFGldwWTMxU9JKS2vis6Nt6Xo0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.14_1533817028427_0.30279739156333263"},"_hasShrinkwrap":false},"0.12.15-alpha.0-headerspolyfill":{"name":"teambition-sdk","version":"0.12.15-alpha.0-headerspolyfill","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js --exclude=spec-js/src/Net/Headers.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.15-alpha.0-headerspolyfill","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-TAQkgeFkTBupgVmBoezP3v6IXD2fs1LQmCAx+Xbp8WbDH0FC6/whgi0QOCl2f7B55A5jL4dDkm3s1cS+fERroA==","shasum":"265ac75d7df203976e9dd2279c14a364745cdaf5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.15-alpha.0-headerspolyfill.tgz","fileCount":374,"unpackedSize":767183,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbbPsrCRA9TVsSAnZWagAA5oEP/39E3kMTyTQk1SOKe6IR\nTb2glK/qdvWPJkSv4/wGkSOq+wHfr0r7lqQ9NcMkL6wqNuv6ndKTVcKL9xss\nwIyZ3shT8CVlhqVh4Avspu3PLOMMEkaaqm9vKDHGcp1GRh05PRJjJU7+KsL9\n9nr89hwkFnnhkurMVyu2cNNoxWKSkXvUZgDzQaF+akHS474gll+X8Z2F85WV\nVWKRqNPlOYeyQCrjgU0Osr+OH5ZRsEOOt3sGI8HW8tTPjzSvRqOKYU1r/MXH\nJ3QkA6ogz2YhZFHCz0OUWngZr2ALSV6d9J5ENVTVBZ0mbqr5Czkd/TcaUXUe\nxK9JT3+w5gD/OUXUYNvMc9bY5/t1e6p4hzyj0DpyNw2LXvf851tO1GqAjPwk\nl5FqLUG2oLeJDCa6Srwo1syalO0zCi+K0kGYvPYQEpAHjS/VLZ1xMSbkoG5w\nEy/MIuRpu1AXZvHRhtzGZafm6q6klhTlZNGCY46IV0Is/hepMTyoyueFfVB+\nWQTPkQFGxoZT3NeDIejo9ioE6F2RDClrrYGXDtTSSqnW1CZGF8RA48oRYieY\n18QuotONMeGiw6WzragNuMgbPGLFevYeHKhQSN3m9nBxE+aRh83WmOJTnLW3\nU1vziCr2ikwXEAihm9uKi4V8e4nHuniCGEIEp7ZyGV+KtB3gIgsXdgFkbbVE\n9lXC\r\n=aGn6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBK8SdIKCPZPmVnZtBGYQdCw4NiQvNkF7wmSHnXrKyNbAiAvQ0hWAAjcFY7jjUPnmZOKVFGAakEu9twtbkrqrmKncQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.15-alpha.0-headerspolyfill_1533868843057_0.5100865719006669"},"_hasShrinkwrap":false},"0.12.15-alpha.1-opfetchpolyfill":{"name":"teambition-sdk","version":"0.12.15-alpha.1-opfetchpolyfill","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && npm publish ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","version":"ts-node tools/tasks/version.ts && git add .","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"optionalDependencies":{"whatwg-fetch":">=0.10.0"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","dependencies":{"whatwg-fetch":">=0.10.0"},"_id":"teambition-sdk@0.12.15-alpha.1-opfetchpolyfill","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-elcswgDt3ZmdJqDFjg35xujoZNYNZoBN9bLKw1SCzVHyAy4SEgRMCVzmiSdkqSlV7T74PuVenfrhj68c2jy11w==","shasum":"cfe1d4dd3c5522ef9f87d34c8ebe3df747dc5a9f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.15-alpha.1-opfetchpolyfill.tgz","fileCount":371,"unpackedSize":756069,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbcOOyCRA9TVsSAnZWagAAXyMP/0Fk6STiM3zZBMOA0z1K\niMrhZ8pt0qZx7CWjARSXb/CC5opSMHKDGnOOZtutsoUvOYiduLy5E3nASVxr\nnoSTLiiilz3OOK0iA6/0iViSTiUBUnvUg8RaoipxAI3Wc6fZ1ZUhVsNGPfHC\nxo62qXVH8mYVwzWxPwi6sKqqPzUyShFlt9ZVitAuvCcjWIgFtmECBtlHp1qW\nHzPhPVdbbxQrKHLvL0o/+Afmkl1qnucxhA+sD42NK5k7gwfjKxLoKBuyemJp\ncAA/fWKSTk1+/WuGAlN5qHogq830ebbAn7BYt4KILUNhGgg0xqmg3MM2z7P0\nIAxcfj6Q2gkJb/r7Ap2RrO5cHCE+Rx685sS4hbOvWkNgohC5VOl+NEggxLMc\nwN1x1eGY3OisnSNQ67I2mECE2uGZLRlank2UMJblW5HpUMDhe/41RHqAH83O\nq6c3OkJVf/8UpytY+iu6Tu1vHzaBo1AEVlk4bxfllbo6LzzOsI4OJJchZd+p\nPTMZfApPhzHRz16+ZiMBsFCGQjar650bdfhXaKKO2l0wUHcE2EV9Kp0Jvn1A\nmOobt/e/xkwM0Ct+4aHdLS4IuzPJE5mSSrT1qM8d8JRFwRhHVHvgQTtqLPmU\nsMCr5tJcrFAfVcFpxI/35Gw3hl3ZYW1oNANNwwaCY9kCe0QN9ZIc+l98X5wl\ntAcM\r\n=q2Ig\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICR0dH58u2JSUxst6598TXiSrGTHC1pIXvQ2ELeE2A6FAiBAsYm+iFWSuMK5gZm3JMrzTzfmTM0VWwnnQTcoauplsQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.15-alpha.1-opfetchpolyfill_1534124978203_0.7205091804258503"},"_hasShrinkwrap":false},"0.12.15":{"name":"teambition-sdk","version":"0.12.15","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.15","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-wZ4tL17/xiUt9knnHm6TPZbbTQqnLbhyt+Sl/CZT8lvkeUvmZqO5jcF9FRpwdvFE/P8i1W1yHCrFTZDmw/vlZw==","shasum":"f82d7018396030fa5f6581beec6137ce4551ff65","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.15.tgz","fileCount":371,"unpackedSize":756217,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbcUJiCRA9TVsSAnZWagAA3V8QAJymycd2ecbPRD7AryL5\nIWcIWw97PIW17YpLXyfXE0p200B7/sfH+ECPX/fbQGNFMl9eUTB5ewTUaP/3\ndfPJOnv6M2KFARYjGrqyxtqnc6XAaxRQvMu71Q5chgSOQk07qFLxehEzL9dE\nHsqkpyLHdPam7wzRWTCw3nlhlFh7oMSpj02cIu+1K832MZxIJF8daEVYEFqD\nWt8zPtDAI9cfL1r+ERTkrg00GS1L1qJpGw/QJS8EQ2yfts02o05v0K5kIqyD\nA+cfpLX2wduZxcNq2UMCeTsKMIHtRXF/IbA8O+KZI96duLD2N8yqYwX72aQM\nLmH3F4UohOyPuHH/v4/v68FG9Wdm5Ma5Zpt9KsS/EEtJKxIZFCv3G+0Ikh9I\nyZbwckv55yEjyOu6Wydx3vX4eGjRWSchiMCRiZgIdUun4XfON70ITWswJu3/\nq26IvSEEo1brsTGtZmkbHQi4PewYE2gD+PifYT9Wa6v7Va2AbwtC4eFWnKBQ\nHP4lX3Oa9vqvsTBh2trOxgAAYcJHzaZOQwK4D4ADMK49loqJ3Ldr23mz93o/\nGqT7vygDr5ywrOHgfgJHzK5e4rc1c/iUP2STa+pUs+4nOBz8NVpIJJDifa4t\nEcg6qUwzX0M7Ro9aV+TgDKilkkY1ucmigqYEsthJ97gPpIJKuizGJcW+JfWX\nj6YF\r\n=q3xg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDakoog5xXVFQ9uUU+jlKVHvBF2X+PanMKzc6dMSq8/SAIhAOg4/Wvp7SZsWlj6QGk9Ft+vNCT8bC2oKQGSu6rLae3T"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.15_1534149217824_0.09990280231294646"},"_hasShrinkwrap":false},"0.12.16-alpha.0-testplan":{"name":"teambition-sdk","version":"0.12.16-alpha.0-testplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.16-alpha.0-testplan","_npmVersion":"6.3.0","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-Z/5VdXLFAX+f7Vq17kGFcYLg2zr3sFwIe8xBjDKA5UpbqtCNKeWNp3smz8hriXNJbG8e4M98BJOjIPz59fF6uQ==","shasum":"329e073a1adbe2b29f66a3d2f0573ffc8e75216d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.16-alpha.0-testplan.tgz","fileCount":377,"unpackedSize":767152,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbc8tJCRA9TVsSAnZWagAAgEQP/jLh5tSZrx278MGQCgIy\nZr8MfmmhfUkdkn8nudLcrAMVgAYYDY/iebuIEErBrhZrtMUrD5U1+80vfpBZ\nS0Nf9QFSaVW57t1xKQb/NoR6binluW05juJUKzyCuVBE2/TLvkyxq5CDI440\nEG26tstFleaUzEW+zybPgJfFVuR6oxacUCjH8jjqcp8fzZOMnGf7JInIXygE\nCCvlIPe1Qn9asWJs0jjbFAGslKAq6n6teXrsQtnVGSnU3Nk0v1vKkzmoJO9s\n6a9svNZK35+CXGFkuZE5AmfUm4CM8t4jmf3dL/T+l2hCUyJyv3rv2MJyt+QQ\n6CVIIVLrb8yigv4HEdalLrFXXhEeTWSDSUC1HBsuwdgZ1lKSTEBDAicvBwpB\n5cdPtqZetjiM4Ivho27M1RMvqzFtg+MUhdso1FjQIyTJdXetZ58SXU2FbQU0\nX8oLcfVPUiKeQFjJdFxNWTz2RkyZxPHy5GKwuXLBt49XwiASIynaxis0w9o2\nhybAZtuNvn5w2i1Zqte/5Y5V3LtqEnRNfJDUd+CbOgTAcGHdekNrqMBtWP1z\n7IXlg7m0OFMxzcAZ2XtCHgaf+31UJSDyXyOBMwMocWLBmoU9QVwIpaa5tePN\n653OhjZFb0ANgZ+6k9yVYl93MfJyHtGazJ1cMW54fWlH8XxVQqpRaukY1p+h\n2Wj0\r\n=8tDy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDRGNB2zyhSTH3JR9JIbTGR6Tjf4fklrlWl7j9pV0Fj7AiAipOUqUrjFiBA//oEC/ExlDDSbQOAfFtMtW6h6vbto2g=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.16-alpha.0-testplan_1534315337587_0.29163142970152256"},"_hasShrinkwrap":false},"0.12.16-alpha.1-testplan":{"name":"teambition-sdk","version":"0.12.16-alpha.1-testplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.16-alpha.1-testplan","_npmVersion":"6.3.0","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-glNe4w57JdPXwYKzBpaVoiO3uax/ZarE1KYQgEuM+9yY8ZqV52Y0B6+Xq8/wfCsjkJ6jmNgHmHYJpxgOxXnSoQ==","shasum":"6af5101aa510bda4a84b35d8afb7009723400850","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.16-alpha.1-testplan.tgz","fileCount":377,"unpackedSize":766968,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbc9J4CRA9TVsSAnZWagAA9SAP/iFEBljswC7IFjMFtLkM\ngqfg0KLqw3WfoJRJRikMVFz5kEET4Vrwn/ntpGKJdjZsW1biUQb6zb/4gRHP\nP+UAJFloicrJd/8Vp70AG8BzHl/Zi11R5GvmtBcwc8qz22S1AfMaK5bC/4Al\ntW5eRSIKWMQiXJbWbf+eG/6yqKE7em40q0UEwejdQdlzxlJCDJkJVqsFum9J\nAtUx5M8qxK6t9dGc8aK63FQljScPiSKfUs04OCnrD9pTpeclXDoGQwrATb42\n9GR6Na0zMqQ9kwSA5k8WWpGI4cYEVYQEGJdiV3Sb9FKPtwXdwolm7uovNIdL\nJ48d/CFqhpYB0CMn2BeE1SsL0/h9IooQGvL9Z7kUTlICnR5Y4Sp4kid69qki\nvrzQ7oh4FMzl/6gsB1v/z4j9MWZcOq1LbHj6FZcuLnfczEeLHtS9NmkrJuxV\nz/GL/FNlAIht8xiIiwA7++97kivHdAd2ngKDalxQ7DVb9tOLAO/JM/aL5g1e\nvPWq2r2QdZHK1Lpsiixe4FTYDk12BkD0Kx7ptuMLQ4CXP5gYC8AxMcRlW8B/\ndG1brqKmQTGN6f4pDePvI7sAm9srKzXGRMXK3gFLnmxzXBvUf6+kIuRTaRT/\nxZ766ZbvNITDkkLZS54cJHwwIJrUBOgJNqF58XbxHVtmN5C9oOx6VMqHlJRp\n9n77\r\n=ncaH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEqcN1tB16C9XAlMyqDI5hVRr7SI0vd4ObWnMysYZ0frAiA0aJfGoVqkkngL/+CU0h5n50+64G1fXaHZ/Gj3puNzIw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.16-alpha.1-testplan_1534317176668_0.2941915714858163"},"_hasShrinkwrap":false},"0.12.16":{"name":"teambition-sdk","version":"0.12.16","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.16","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-5bnjbBdaAMmwIA2uDQC/i4Ehwg/Dxsu+WlaCXWt4npRGlPEC7XbBSeJjqlxB64MJyHOxF5y+GMLqYHqXmtVqag==","shasum":"f42eecd3c081cbe01685c253d73dee63f220cd0d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.16.tgz","fileCount":371,"unpackedSize":756672,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbc/9SCRA9TVsSAnZWagAA67YP/3+WAi6fL/WK1VdoK61Z\n4lpYx56y8PmruQec8YfACEVw+WT9OF5pqq/3EXhtGVI8lnarh47xp7o5L7hE\nitu5IM3ovg7FanLCW82oFVDsK2npeoeIQfyzlrAUk6GIGHG2lYYxfiLO4oMR\nZaOpPb1Pc4obQeahFgb6mkS6h8yaQsZbU2cdOvatK6N01PkkE/WjdxEx4oaq\nx3H6ywFybxdmBnpKvU4jkUT8RaDwBL8QVViqZhpwuzbcZUtvHNRiQUSK/AR9\nGrCrJhfmrWFFQ10c4QaHPuBQjMGozA8c5D41sJmw0/TrrQXd1HiyvKxmrql8\nHK2jjHV4DdGN8KHr2HIRAW2aHfjiwxAfjbDYEJLlbm7obCSUWQytkks08Zml\nnJYvJ5WN6H0u+jbBYCxAL5Jj7BhrpNIIBnGeL1I0Zn5uR/ZQkuZlng3tG1+X\n2xPh7kotikQvyI5p+53M/W/N4jJPknVn9cA5Vp/yJOzhcTrcyfkqqY9M0vUg\nDzgKPY0a+psuRk2wD3M8Wenc/0RhTHACDMaQf24W6EzmkhMjnYQfRvlHVtGJ\nG7RoXPokWg+UhODMt0qkMpUTPV2aqm7+0iDgME/yzO+XziCddNq39YpsiLf6\nUa860+IYcZMe3wksLkQNXeXS/E1b4qx5NVNEMlh38MU8Sq717QnyNhAy/f5T\n8roY\r\n=BYWc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFRfOTM3ndcWzP4hBqNgf1GBoLTtC6iqKGNv3wwh8fjHAiEA9PexAz69PSkkmCnYySYD+ocH6LjrsVhyT1ImORL3pp4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.16_1534328658433_0.8721033276846362"},"_hasShrinkwrap":false},"0.12.17-alpha.0-tasktypeicon":{"name":"teambition-sdk","version":"0.12.17-alpha.0-tasktypeicon","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.17-alpha.0-tasktypeicon","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-QiCkojQm6uoVzBtXrLi3F38z1o3GDUuUZkMZOUPWZja5KRyYoda0ZPpVIehBfIZjfQrnLZyoOrf1X89yeLMnJw==","shasum":"07111714aa4765383fb136d9f4477c253f90b3f5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.17-alpha.0-tasktypeicon.tgz","fileCount":371,"unpackedSize":756756,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbdNneCRA9TVsSAnZWagAA/mMP/0NiVRuq+rgjxDRFD4nL\nxDtYCIH3KYK/kSrOX2FbmV+ppXSVMrzlXOwvdJhpqQeibROEcr/I7xkNXYUD\nlvrcrfl4soyxd1uckuCy7n7Eixl+KZQS9i9ZFNB6X4Lh7tRd9jrQ0oVONIAn\nHK3noMtkS4BnoiBnXoK7LboEnFltnb3HHMLsm4Es1C8OvMcCNw4USqDKfDpH\nqt2Yg5O6gi/r9fh2iqKNWrf9FK/TE/+syPUVNiWFpKK9JJBEcJjxNp3Aryzu\n19PFsIYZTtCuxRHwYVCVv0akSl7bbyuQN3zq8FcarnFCZijTWR7cvVfgXUvB\nuR/CpdM6wAcr6ODbuIxExrHhPwHG3IVNj2dzQlcCDs1+E0tzrwXR0iPlz9PM\nKGYoEVEWUgO7PT+1ZjZKgZAXx/TY4d/WBddYxnld02dukRwL4w5BMHoZ9CXA\nD2cXbe9zxXsQvbrI6g3qcX04cnW8WRN2b7LTqCcsXCVfJrNncb65iT8uDz/q\nT2Bt5iUiFg5tkzjF4t5NM08Cjq2zoISZ+s/2T//Fbe5jK8h+8CMEEzp6QcCB\njfBCxiDxYGiCX/ePhhd5XqLUqOiSnOxK/DT2beIRX9nkuMqRx4+xRr4xVseh\n6FVSUEwdLxtkAVybWImyyYM6fv0pMhFS44ULk2gNzyoyhsIyY7d3S6o6UJz3\nRD4J\r\n=DJpS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGXuFN1Hft5jVJTejFE5ph6WRwYbUKDV1SN72KY4ET+nAiEAygUL9RMMNBV0M3dO9EEDxZ95lR/zUK/oJTPGecfbAuA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.17-alpha.0-tasktypeicon_1534384605943_0.626192727702477"},"_hasShrinkwrap":false},"0.12.17":{"name":"teambition-sdk","version":"0.12.17","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.17","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-VICgx3Sw77XPpirVap1a31N50e3RJCK3YVGpi59RgV6LFGcydKqyfoz2TrQhxRDsCjrWWKIhmCEsOHp3blzMNQ==","shasum":"a7e547f8e4f5666cf0b4bd7a73d89d8b66f251cb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.17.tgz","fileCount":371,"unpackedSize":757061,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbdN0mCRA9TVsSAnZWagAA9iQP/3IrKhqlI1iMdWbdfC8D\nUwhYntE+qUWZw/rfwWJYYzEGf2Rp29EmVAXxmI97hPTlVxlJgSYX8b47S01w\nlXE7MVcqDFirejbpUMHYAbu6iD66NcHkVbqwqUXwyrle/GShkwa1mo1iGxNi\nFjaFUceDpu/RP1YIChH2sek3swrHZje2ZRzyJMpqgNj4sKj3f6j0H3LROZoJ\nY1m0lqG0hZxDj6IniNxFfbXZCBD2ZKPVH9H69lyp3CymBtpt4qfyyOVdQ3JH\nID26a8MufDPI9mQBIuQfh48A3bdcHBrllSskONexfI5So2DSfGlyZUOg3LWs\n3kv4Cvv7kNxLQNKYMQepppF+Ymmlbp7KPLsnWXDh46+DKe7YeMpRAeXDQ02R\n8SSmwdVgZ6EMB66KadBmQc4o2XAWF/aKnwZPkxZ8b0zG9ZLG7n1GVM6z7iST\nzJcjDwHQCVP/aiDCVbQbLFfqXudR8tQdmZGDrzR+OsxHdPdzzqtYTxkI5imX\nLVM9qJL5RFB6syP7Xd5EJK3L4zb+yNuRdCdqegA9jBQK9kKw7LQOds16luIq\npkmS08XoI8I30rJ6Bv0olk89qR+64EbrKgdYTYBzUrfDE0wiDrgL9z1Tz3Dr\nHHnxly5R4PVLsk4U856UERMsyk1ta06hP5VZPyy/zYzEAdXhY2EiEevFFFdA\nnos1\r\n=bFvn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICmQH5XX7bAJ+u0C8uqABgyKkTjS9HQZ6TeNTLpl23dhAiBVeSzcTRGNskxAuaWbS5uZ6eHDfUD6khZ4cmfMOgtIQA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.17_1534385445444_0.532137495194078"},"_hasShrinkwrap":false},"0.12.18-alpha.0-taskdep":{"name":"teambition-sdk","version":"0.12.18-alpha.0-taskdep","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.18-alpha.0-taskdep","_npmVersion":"5.6.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-8topSuCTVYVTQJOH6z2jp+wC3RpqJ0yr5GqHr49zxDytUXrBVJoebEkjRFdOlxCItI5Y2VEPtsDQtBm7bYRbUw==","shasum":"46acb1f8f899cc23e6cd184305423a72dc31d369","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.18-alpha.0-taskdep.tgz","fileCount":374,"unpackedSize":760433,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbdpevCRA9TVsSAnZWagAACEIP/3FtKIzAeyp+r2ddO8o1\nicTVpYvSczD8bxTvcyA38YhvHwGpvUYYGrR/O1l13Ol4VD5JrB8AvUSuPQ5n\n3zulOOGKCPZkQ4j5q7FyVdb/i45OMNnPEeG7ie1MDv7XRZX4NxCavHGR7ph1\n40xmPR7KVe8FWZ/Vx28Z+f5EbT8o25uSunx4xw7HPbiIiTMAuiCfqjoR3ue2\nmxysWu7HzrMcgQ17b5c+jLLCw9jIOQQCtdWNHKVvqdyVkpK8R8BSG0W2aw3A\nGRKlGbZM7DoxMaN1S8d93UsNiEmC+m/rjjr1qfDmwFNkZHAxtY4wmLE4NV0K\nHGzLLJ8JmhklccDuIIbpFeNp6t0glVEoaS6L411W12KeHq3BIJBNvXh8h78G\nHKLBIA9HPg3sD2wwXR8/kEH375V6mE6rl6QfngTbg8kfjEMB3FMVtcKapLO4\n+gx1cD7uedN1mu0kadp6fEZXxnDc/CSmXUo9Krl7bmb70XReHTGq5zB9EO/u\n5MbmgXZBXBPPl73gLxuZWYG/T5iA7m7A8Mexw1XRyDBO4QA9FP/VhQts+IQq\nSyT0PwewDfyFIbJl5umBUORbm5iP22UvB6LVKSRrLkwB6nNL3WSIBRYSU628\nn5fxQ1ET/r4cAyR2q7tRGeSFdhrRwp/gO1UZuoW8qcVrnLHdWGfE1pItggdH\naEYu\r\n=hvAl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE91kGr/7xLubf7GDdwuVCybAQAZ3cyrFWrEkEzTzTelAiEA9p5HzmO4QdMqzToCnYfBrJiI7YE/2Yob5iG/7pfWtvA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.18-alpha.0-taskdep_1534498734332_0.48893916454474606"},"_hasShrinkwrap":false},"0.12.16-alpha.2-testplan":{"name":"teambition-sdk","version":"0.12.16-alpha.2-testplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.16-alpha.2-testplan","_npmVersion":"6.3.0","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-1Y7Sg/sFfsxVLuFb1vleJsDPxZztOGLXglV2EHissU4SUWHxqfHkKDEyPAXIVfKH+ouSOrcxWsv/8SW606jnFA==","shasum":"822eac96986a53cacab11862032ed3e6fc64a01a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.16-alpha.2-testplan.tgz","fileCount":377,"unpackedSize":769044,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbg49dCRA9TVsSAnZWagAATpAP/0kcfZTpExrfD20QWsfQ\nURMnyClJ9eLpkF7moBCPKPyStvc8QXmUgex7Jo7sCcJPO2tyUFsyAhCieLB4\nKW+qHplcgsMU5tFROtZJUyNvKiApAu/vwjWHhJv4BV+8Bs7/u5pJR1k7PZcx\nYySf1FbZxJoTUJpCiSw/7mHY+m/X02SF1xpZRpQ65dJfFyAMx3TNPP/7GS70\nfCIXaA0zOYuEzQ30u2AQSILNgnGQNrtn1E8+xoCr9Gwk1RQCsuIpB90rO7MT\nUnLqbspY+yqYWXAOc4sfafEbHXcPoqrYnlGMyDPo+mX2r/b29Qkg5OsbVXub\n3hp+/WxpWCXxl9I/EoK7g4A/JrJkfoLbYAbQ5BPLxmeLWkNaB3pELhITTPPd\nXTdKsL8kEeml2uuZJvnaChaxohKH1UXsOUxOS/iY+AkTc9qJgbXRM6Jptbx8\nYe6WnhYBAZLCPWlp3t2q9piEPJIRAbsA62tG3WhLji3Y4cvgpL070J/AFJ1L\nUxKHOGjbmSzgLkTJyh2/5KR60hIOHn1StfG+y+99bAe2Mdu/FHdxQrbVCvVS\n3naU99YFGyjs7WIYRQYT2RxfxoYVliNg5fAW31R3ZGq9HqWBBkuMNC1SWyH2\nzcnSPT+/Q6NkDrqP2xHL1TSFrNuBNfCtWt0TTTWXu7sM3XSgnc0/TBI6rGTc\nD5nf\r\n=JIVX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC8KI78BpnapyFt2A/kx7cVhXn1WbbUs7PYWOy8lJVh0gIhAK9a8vGBGeBPjGLlex/rtEQA7LsYKklF/G7MFFDW39h1"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.16-alpha.2-testplan_1535348572553_0.5433874326184776"},"_hasShrinkwrap":false},"0.12.18":{"name":"teambition-sdk","version":"0.12.18","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.18","_npmVersion":"6.4.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-7XE1czrxVZvjP0nhAQrISLtcEixFisLk++ULYL2nkI/jTheaV4N2d8kDQPVv4NCK00DHj0Kai1TteNUgVzu0OA==","shasum":"28f19b65f12251f98f0862ad5a163bbe6703ee1b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.18.tgz","fileCount":371,"unpackedSize":757499,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbg5DnCRA9TVsSAnZWagAAV4kP/ie88kONLqiz3P0Ikhy3\nE/OnWN0NJu111jPYWBlTM+fNphaqV7KdXBoLVKhjMeHArV89zyB1JC4+a/6l\nMpMhixpXAQtQ8rQ6ALas31rzLllLD+3iAkBIu2NiHd+hTKzq2d7cDgs2ZnNK\nKzzdO6xJt/n+dxgfSK1mzfERnY7AMlYQQiFVkLfX2ZPiic1IHiUyCm4o6MFY\nlhexsNjS5VKsUq5c3n8bPWuvWXrEkWD5qdOz6krDjBpWY8eXac+WnPoxNhC5\nOciKZw4Srdm2uaBTe2TPL2mIP9lZSvO6u/dMSS0Deq2Oqr3qyRFM6gCG/TLw\nPZB1ntvmzvKTWUYbhAmRRF+GEKz4GSdLmtTXqmsaMMAUVtmwQPUOMysfYSSo\nJdHv8yMxG/8tAi73z8vPzYZvqUSge/96CNArmkLZ+icKtWUgQf+8poI4p2Z/\nvCE3ZJLu0mN182RcFEJVNi1tSxWNn05lfOnZzd34KyO5+mcJ+FsuM8goz+xP\nIWKx1hYxSaEg77nhqukjkUxpltu01mOywrwJ38GoCTYcFrqqZv8d4vpD+kFh\nieyWqQawOnX14lJDk6wN7jMl+/a/SfkPOUmEkD0Uxg9n5JibkOIbRDnLrR8q\nIzTiTVpx3N0pmhaa36J50iCjuqHEEsgjzZAY6O2dlZRs+gc5p61Ih5cNAqH8\n0qVE\r\n=YmTy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDI7YZv0fop4rVh7WtDOs47EcOFMTTJ0byGk3oEl+erfwIgTmYyL9FmU6SqsnkQJfBU0FtVV4MaWyKsuaVkD1Trpso="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.18_1535348966872_0.41742138117478267"},"_hasShrinkwrap":false},"0.12.18-alpha.1-testplan":{"name":"teambition-sdk","version":"0.12.18-alpha.1-testplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"gitHead":"a9053b24435ca5a06679a202ffb830deffa740bb","_id":"teambition-sdk@0.12.18-alpha.1-testplan","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"irinakk","email":"irinakk@hotmail.com"},"dist":{"integrity":"sha512-Omw5Dlw6OREYAKecDwWznqiVMmRTLFHnRjI0D8krYEMdyl5Hc3XurEYgIMwPo7v+iMC/biffW6ebdI+dgjwoHw==","shasum":"8af2455f26c32e4568bdcf94a5d5097a27164e9e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.18-alpha.1-testplan.tgz","fileCount":217,"unpackedSize":833201,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbg9j1CRA9TVsSAnZWagAAB84P/RO8L3wM3co7PdjCh8AR\n+VBidQAs3w8MIV9Cd8Oyh20Ej0DZJdrAfYYxM7iqZW4dhIboy1Wyvg7z0bdF\nYInPlQC1CVSrQAl1mj0hI9Ivw5uFqBKV9RtwBcJdI6GTfQpYbbQbtW4hn61P\nshJIVPmldo85nfgLqf7HSjfCEg8jDcaBsydKkbXF4Fsd6RGbBbfKo22gx3R6\n/xcPyg/5aL57xu0KD3ZpKiQ4iTuyLTnDsJQxy+2lYFjfpKJMOenjVEVoNrCl\nbHtMtqsdM6ajekd5p874VhgzmSgARjPLh+6r4FmA8zD7Fkwrjs+V9lQbh5Nd\nKLRUmLnEV4KTtjhIITvArNqg8xDFnhOCodu27GLlQ5/wtU7GNkDm92ESpAb/\nUxge6CwinpmZ61WFPzuEyPlQXCi/Hlb6cVGAa1ytMIp5u7b5Ey57V4bbWWjW\nCRKfxgatJtA9dt9Hl+Im6/hW4BpO2twW8EYbIDyYelUq/G3aPG8sqhF9zSh/\nTpcXyoOvpfKUx/XDKH77GXE82feAUQpRIYK3BaYqOBpc9I1kwkkLgoJyxHiu\nU4K+TMqbiQNaba0GpY72ZYsBlSndnJoQ8x+AgXmmR6jU4TF5CsWtVcO8XfLw\narI7PocopBsYs1748XKJ4XrGB8gnLjT9ii70Pi836v0FfHr1thfAqaGu0Wl2\niMLN\r\n=kUul\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCj5zPb4HnJfFpg/6Z0hi6qXmjno1+pHZDplqc2OQYAuAIhAMoxz9Y5Jl2I1zcK4nX8rfJksCxWpg1DYQf+vpAOZ5Ey"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.18-alpha.1-testplan_1535367412287_0.9879705256227662"},"_hasShrinkwrap":false},"0.12.18-alpha.2-testplan":{"name":"teambition-sdk","version":"0.12.18-alpha.2-testplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.18-alpha.2-testplan","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"irinakk","email":"irinakk@hotmail.com"},"dist":{"integrity":"sha512-zIx2ZSjJpQXeN8daVWlQdWdODoZi2HCXaWc/MJXaLeaibT+JThl1+GwW+WuAVHpaf/Fw2rJ1WIFNb7reIV9X2Q==","shasum":"2e48076c40b1a6840bdadcd2cc826589749baf8b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.18-alpha.2-testplan.tgz","fileCount":377,"unpackedSize":769894,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbg9pdCRA9TVsSAnZWagAAdc8P/jhtovNAUkAPUQDwG6ay\nHnS60p4h5sQdspxJqAZP3RYn9aAd/J8WggORDejcrPbgPtOw5uTuClN96siQ\nv2T+dEpHxWfqDzbS3wPIeXCfIF//z9JDoM5oHFppiNacTetm1kEI4VwDqaJl\nTdlOJ80REa4U9/u1RCS8gOxj6jvyzoUst+xtoAxpApASQUiGIuVpmplYJoCa\ndeQQ5NMtGxUqc85XJXqLwqakOn7crjoyghyK9j8yT/dx6Vxklmb4YDdrhzCW\nzNxio+haep34Fl4q8aB0+Z4pLwyzphO9JvNsvArF9B1NENqIlutP5gOB9kI6\nHzz+JuyIx20kIzrhd41NyrbNHSDYvpK/gyU3CJ2BcERAt8AvFOb/yiUlXF2S\niPKrio/D0wOWXtjFEYFeT7WGckDn1da7q3I+ilMMk8laFlwrNIxBM8sNHKyp\nGuYAc20Vn3ppwVMLpu5ZzppscuT/CP+ShLfrS/jGACb+3FJ2ziUzsQ71pSAD\nHhAldEE6PeMh3bZ+H1HhTMwfUFYJAqlotSWrpfW8Zl9z+7eDx/HRm/+/tRwN\nJqlhqrF/oa53o9fG6AR42NF6tVtvZiVmhPC7cJMuPssQOrjYmee+ggv/jVrw\n8yh5a5MeCb2foOgH/3lBcEAwXTrwUh1supAMOW+9QpmkGLBAO2oUwSBBW7TX\ngg5M\r\n=e9Hl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB22MHOpajaH1Y+bFsKKmDKZ1bfJKYsY55JqSmVKDgdOAiBh98SHcyNkHySaUXH0/KcRpPMqHw74jrGEusMP//Hf/A=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.18-alpha.2-testplan_1535367773139_0.6622582458591677"},"_hasShrinkwrap":false},"0.12.19-alpha.0-orgowner":{"name":"teambition-sdk","version":"0.12.19-alpha.0-orgowner","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.19-alpha.0-orgowner","_npmVersion":"6.4.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-LUnjfPRl4v4EBNhW5qonAJINe0pm5rHZSSUy7UP+4dcElxBOB5yw61PiRtv/t4H0IrkKgHWw/ktYYPCRbxTv9g==","shasum":"34f148f1fc8e6043df7513719f435a7f748789a8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.19-alpha.0-orgowner.tgz","fileCount":371,"unpackedSize":758294,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbiNYaCRA9TVsSAnZWagAA/c4P/27DtskwgdPfkEJMte7D\nD16H1fp3Fhqe5Lv9b+y+SwvKU9un2anNRgOZSDlLSLfz2Ej31DM8jnPB7M/4\n+I+T3673Fn38FOgO4EB2obmPywvPoaLF7miF2WcXGntnEZvLxk98XJ+R0+nz\n5uXHJnvgmi0Q426hoYhJAJgUxpH8tzlvLJmA8JZwNTdTPj+YGKh9tAe6MCnu\noTe4/fJIc0/LDpqVxCBn666VfVXlEgWfr1ftFv6z4ZwcOhI3L4RcbzC5fRHL\nT0ddZ2YWfdYdMz4GQYqU/ZfzlVV9m0SDc80D4YmfeHlUfBDfuNJ8csNgD5av\ng3VQyE5gwmJIJHRDFJY8BcmNJevc6rv6xILwJyz+QRTRAQJ689dsg6loXm6z\nzGawS13mk4CPc0DnBW5S8WD4h6mQl1TnHmuvzfNMJu37JKeeYDLqGOhBaBKp\ngummhle0Cs3tWFNUwDVL5MhYCC7IAittkfyBzrcbewB/Okv+6irowXzYw3Yt\nY47ty3LnnbLEl92gUQhMwZXR0j8AAmvvd3XLgjn6c16USsz0wmLiFcnQyW6I\nmh9MXzL3k4DZuGfOr2mY/iu0PBD5VpOYWu1XAHM6VxG5z2K//aAIVkvamoNp\n5XoeqcGG/fIeZeuVQInJAdBFYbzIKtM23+Y4v8Iq//nVVhzKQV2ZZlzJTtWZ\n3vMB\r\n=ahYS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHgrSenKVHfwBSyWUvZP64Z7btJ9fhKfSk4M+4tz0AcIAiAZmFYEgjEpbFCUitdU00KWge8d7w+rjBGJV1FUsORIxA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.19-alpha.0-orgowner_1535694362050_0.9753422105605056"},"_hasShrinkwrap":false},"0.12.19":{"name":"teambition-sdk","version":"0.12.19","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.19","_npmVersion":"6.4.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ytDzG+1H3GanhIGRGjpMgcDY0QCjfKdOcrS1ILtqVtNXYkM/onWxpPbjIxuaOWLj74rGhKaE16GpXJr2+/hchQ==","shasum":"779b6ba1430495573344b96523c86c66285a8de4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.19.tgz","fileCount":371,"unpackedSize":758277,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbiOFeCRA9TVsSAnZWagAAW8EP/R5j/hgbQsWZOKEhuSd0\n+yX2b0BDHc7gxytaHvJWaOV7I6qTTXeromhYo2F8egBGbVV9l3h1xN9xfjIw\ncwx0kcUtPhJWAYU1qMgO4vxYTqK37OTQxrQyMWtTG4kND0/NXWrStrBUl5qw\n9Mk1ZmgHWtd2wz1f73RZ6S7LPWxS8RWMZ7rnmQxzk7AkxPaAgv2Cb+dJnqz0\nZd6WZXCsGjCptALWGXAPQwDulE/gGC8M5EjKnBa66+zc6QtPu7BL++OE1uKe\nXZRTQs03/wpHq/Rq2m0/ZVMq+XwGxG6bvkmdtUX+v5u8knR//LO77MCdeQmW\n/lEPIQv3eLcrE1bUsNp7x4Sf2bdiKkKz0XchGmTi2vv76AyESht+Kal8/1PB\nYGgvvOROK0uJF83sBGP5Yka+gfPNO0NyLMu8pfuVgtDqbuIhptIbVQMryZe1\nvgfuGiT24SutXe+P1u4wt2qk6B+iEblZEQCqfq9WxS+iPwaBCXowZRyhH+3E\nOUaoC2cEXixjqZ/IkMHYq5cTWcKZn5o5269JsOdclvIJXcYfz+U9Rg6SQfIV\nDNCvNmOBGJJPCYsU7qpG/r6Gp++giLruhu9BtJ+iu1R9f519x5SluMXvpPir\nQUrzGIdRXWxGdUO062sf7JfT3SmhrgiXzxzBEtEAJr8j30QGaxz40dwME1yb\n6Zvw\r\n=zPFT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCxjg+0Zthvs0SRDGv/2cbbW1TugTDzhwsSb+HMhy9glAIhAPUMvtwrK3mSnwQw7Q1knuLi4LwEAEfzVyJEjwpgMdT+"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.19_1535697245106_0.48172075433888906"},"_hasShrinkwrap":false},"0.12.20":{"name":"teambition-sdk","version":"0.12.20","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.20","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-yBQucvUC1l+wyIx/7or99LzfQaGxsKP80iCbJj4GpLJqUpJbFTNICJoMF+n2FPuSaGvvFBVKnMpdp8urSTR36Q==","shasum":"ea67f16033623004b25bb245798d8bd1d4ea8500","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.20.tgz","fileCount":371,"unpackedSize":758946,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbjgghCRA9TVsSAnZWagAAJTcQAIu1PKoHRtEcjPscMdgt\nPG25GfeWDZbYxGI0Rl/tJV709JosXHwNbjnr+x5S3kLF9lNHfGpw0ydeF2Gk\nBbiNnHyqN6S0YO3L+1PA1OUjZHS0QBfQtU90b3WEtBQipd8oBRDEEtLjm6CS\nZwog5h9Ldoypmc0B53q5RJpnQgdUf1WBffDERaxyLwm2+ZTHtOggb92cNpbS\nd401k14Rdm8RR4inx0W1KHYwiWrP/rjlSSYzIrUI0/0Sj15erHfQVkzB7fgx\nlqx4IJ6fdOzW5/8LNT92I9IAVQyYyY89rkzoA20+eXIBbQJzNlxJjyd2I43E\nT+waKNeL7MDWE8gzIMtKbjoQO5Weul7az+z+olpzNYHYF/3PUzKBpykxCWK6\nyCusGzMKY9vDI5Vho7Ba6bwVAUBUcTNnI//XEh9lpr+94bf/MUHHLoY3jFDu\nTLHTUPABmEj1GpCuKSq8BcEU728u7TLI9V4ijRf4Idc934MiEvEI9F7l1CH6\nPHdpgikvyL5R5k15Pxfz0A2Cf/IHVn9l8yonxqPYIMcVaeWOxl32Wzr3+JMa\nzVwAuunPBo38qHZU5KNNG5uCalzPF9oyvbxAgIK+oDl1uJJJuqRrLH8hTGW8\nDJz0vJnWmwZv6dEEQosIFmU+TRcGn1h7uSEBM3hfR9j4+xxAPWve09bJoWPQ\nxbbr\r\n=ivRW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDn5iy6i0btQZupsxZUT3Dino3ce1zXOOGRvzPILnooMQIgDQlXqdwXO9WqoqB9YBTzZB6B8ZRq79nTm+TT+SNhDRg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.20_1536034849080_0.5597545411752003"},"_hasShrinkwrap":false},"0.12.20-alpha.0-testplan":{"name":"teambition-sdk","version":"0.12.20-alpha.0-testplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.20-alpha.0-testplan","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"irinakk","email":"irinakk@hotmail.com"},"dist":{"integrity":"sha512-V+AHqc5Zz01PkJGYfP9T8vApHnh7oSF3da09gZUJ1Csa61QW4zSuLAefsdFOaLr3KXFUOfshTTGrN7+mssrWDw==","shasum":"28532b77a8a6bdd748cbd29f27591eda8618f83f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.20-alpha.0-testplan.tgz","fileCount":377,"unpackedSize":771341,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbkOtACRA9TVsSAnZWagAAXo8P/0qX6sGIImDwk7ekCDQY\n7s9GifrdCFe/56eFc5ZArYZovvm3I6gPgm9shUiic1tcSoizc/zyzGuWTV0N\nLDfnrPH0LMRbvWBeh7gt1b9KJdcFmhPgdtv1lL0w2rcQev2fj4eIXfeGuswY\nFyDEGJjHpopTD6ydoCDp7WNxR821biW9ZvUGxz8KnKbJFzBYiYN7qFfWRW7/\naCWsbsfXd8OllIdOeWtUK2s+fwhMn8V4g+r6jgTjtTs+kA1FtWdaOmtRBe6I\nJQUJ05Ic71FghSs/LE8E4zIy4qr2FzeQqV8JaX+mkhEl7PTzlzLc5GtfLuyE\n/RbVC37kbXQ8ta7jNoFMQsUgs+YJwmJUO9+183ANkAYIKJKQpbYcbDmZKfzz\nmmYPR3WIW+KlcJ3Zy0Jpv7BSDdZ4idol7jNOQskJSLF8p1M2FWiVdCwSaH1j\nMJ+5d5Wgjc4qkNRmcF7AsFiTCKZYvU3ans+C+d+0lb8k51HMA/6JuURpYkT4\nr2YpMnxXoQs9eRibcoHliSwFPrHifrAp/eTDiSVtBwD+gFnRSGD8ZRoJH6J8\nx61nRvGfF3AJbKy0TLY0YnJGFNjcy4Gp0k0NIc80fZ0apI1k/v7zriMFWEdP\nchVqWG56l+7AbOMM5Jro2KuAORyl8RbR2iAusxPZ+/1Bjj7Tbx2no7ci1JYa\nT3PR\r\n=TU8I\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAnPIYI6i/I7mVhMfnzQyH2o2aNjtI4pCFxs8QZiZlxXAiEAolyDqQmA2FgmPFqXTFHvQM+RqDf0NmXuyCcBM/3TRHE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.20-alpha.0-testplan_1536224063062_0.29216275761123955"},"_hasShrinkwrap":false},"0.12.21-alpha.0-testApp.0":{"name":"teambition-sdk","version":"0.12.21-alpha.0-testApp.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.21-alpha.0-testApp.0","_npmVersion":"6.3.0","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-G1I5ON/T28uj92uABPF5N2VT4LWgqU5vpzSYY0NEJT4QcfyyhJ4uaDfYvKVz+DXiNl9lC86n5xbrCnLF5X4qdw==","shasum":"9376da8452a8f7ad4becf7e7bee611d8a0f31daf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.21-alpha.0-testApp.0.tgz","fileCount":380,"unpackedSize":777604,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbkeNJCRA9TVsSAnZWagAATDkQAIEo2dmXe+FnVWRHDgrZ\nzOwqlQj6XTj3RaYeOPH9Pn0slbN3QDMhqiiT9asu0XPk1u/k1wzvqk3+dEBi\nck/kJRYjt43zZdNNVdiWANFUCUAcwHJWR5AFSFCaYsBXs2g9jXAM/jqyiq71\nBZV26EaJogCC0CSQ+wZR2UOxFON0Xi9ywgzzp5iSJO0BSP2NFtw0WG3kmO0S\nLKWyoF9VmaCHYOQy7/xTqlCsmNMsO6bvBUJunw9S0Lld1Qi/RcZd6YgjEoK1\nRu7xXFXchsXN63rvyqwp9FNewuinvYJ2wKpXVGC1qiZycn0uv8uK/MxpDoMy\nQSXy/3mJlol6NX7JqsVjcTHxRyWK8F0TTMjlDu8cxeciLCDHCOxx79rzDQpa\nKRawqXdFQz/WI0dgofEef8oTvPHJPIoA0LCVswiUPboyXVKqjKL0Uak014ca\n90o/BftgW8G95NPBaxVpWBz60YDMTblnro3YdNns5oT/DCHUYyehEoU781QC\ngVzV0lKpz4+WurvZmvCk82/RkoEUoqZcAZYff/UtLoPcnv6HMCne4y5HM4n7\nx2I4zwl2SgNIiUM5J1+xB7rQIbYFB7a7EsWnTwLCYXisa0YNf5yb0wdtTPgk\nO9PyPXVvPxGXHNQNuJTdJoBKmB4DbsQc/mhlYWsHdTxJ5PmfB4J9qKEvwbuc\nG82F\r\n=868Q\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICNng3/wcXeeEvwSOqljGO0zY5hAiZeG6iUy1xt8E5XIAiEAvpnSoEfC4aMmGB5XGYXOvgxZSL9D5R2Eo9Q0bvzrYeY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.21-alpha.0-testApp.0_1536287559908_0.8315885907286191"},"_hasShrinkwrap":false},"0.12.21-alpha.1-testApp.0":{"name":"teambition-sdk","version":"0.12.21-alpha.1-testApp.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.21-alpha.1-testApp.0","_npmVersion":"6.3.0","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-yidRX0G0rEOtqiXTvkjHJjSR3yhTvFH0PbNMkg48Zf+KoZYDP95gUC3DMIrhPykSk8xlStFZ3ekihNb8T7B1Iw==","shasum":"26924f347ac15edf777359886c856fc44fd7e03c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.21-alpha.1-testApp.0.tgz","fileCount":380,"unpackedSize":777791,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbl4tVCRA9TVsSAnZWagAAO54QAJlNQxWQsjGXqCSd4g8k\nZlMYRHA5+XdEERHwoqif8F6OlvNVCEgCgO9ob+GZZcNGTu3jtuycHFi8KFx3\nQUCJhoPMVQQ2juAIeaxt95JwIxRpzJL1HDwc8GjA7wW/WXiTLLd7j4f/X4wU\nvaK2Nf4rnVNnSM/hzkyp1FJLg04fPvgtpnxeiNFuY6sU38hQkhar82hz7K7N\nX8//sfZ1NyKtwoKIigVqcvrCSA404KRkw98yD4FhzRcP6RX5snnXYXv1MF1b\nWeGNtqA4yYj/vnpS4l0s7f69ms438yidBuVsbqRnHbUIm/0Rpda6z+uB/NEw\n4KaPeib4Jcp+j5JiBYLtScBeI9CsmynElLlde8IuBLRjr7iVlFkINS9hv/EV\n74mD22k4m7GMOC3mVy/o+2qX848uxuSWRRcxH1hU++Rvo2jn4Wvim87t8KdK\nsYgfjCKpDhcAgrNULXSNVHT0ns5J1yQGrmYT2rmyEuAmMKhESU1SwW8HlDMH\nxmGOPl6blaWJ7+so8d7w/Xhf46hjxxAx35OG3YkYR1FCyhj/Nfx1EnmLmTwz\nF8Lb3cIFTQ3bBAGpXRc8QsdJGIx5nlUuDlRTApYBkjd2doPkn7Ct4My7vSCg\no+lGZFlCb8gOD6rt6NTZ1qcgxZwrPGb+90ComzvXW286ir17awH8nBOF3+S+\nkIuf\r\n=a68m\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC8zxFVMeXaGSi8tYgQrVddezsE5K17ppIkk487ZC7R5AiEAx8jXHYh6guh5TFqr1HWtaKZctvykKBljss8UL/2c3LI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.21-alpha.1-testApp.0_1536658260453_0.6160799771542185"},"_hasShrinkwrap":false},"0.12.21-alpha.2-testApp.1":{"name":"teambition-sdk","version":"0.12.21-alpha.2-testApp.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.21-alpha.2-testApp.1","_npmVersion":"6.3.0","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-/3FRZXj54tE5NTb8fzM9hRt7ZvkqNcnJddox3SLZYocOpeh2xIzrEw+6ADGplQLInbDDX18aCujyxdsg+7KhAQ==","shasum":"b0b5aba9a2e9fa1ff6f52ddc9ff43ec264d87f46","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.21-alpha.2-testApp.1.tgz","fileCount":380,"unpackedSize":778291,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbmLBWCRA9TVsSAnZWagAA/WMP/1u//5vJCuVoEczoibTd\nzGWimAqwX9lbwH7ebp7NoedMNH6Ewht2l1PZEjXNIzSgssGZo2qRhQFHM27k\nEfblNDkuH+3OMAIRrUECqqoyALqJRF2b3n95Gf0MFPx4aj7fK7AZeumSi+Qp\nub5Ue/3i0KnP2BFA7lbx0LVu5YHsFbpGRBwa8+dqeZq5qkRgbIbvAhdj1dp7\nVaI5QXR33gj3HyqRWpXxbtFUBBfeVoffUMmMtpow7vvlLZDhqq3Ovs3ArNhU\nUSsp0Fzg+0stzYmD/NBAlcTJA7IsvCdP/7w8EdQPIrH7WKAsHGanqwvooQL/\n/gO+QuOupyRDVEosmYiZ17cl9KfvQb2/TgE3M4q1OSGNBCc8BT9W8MDE6lG9\nM1IXU3cfCCR4L0U9w65q6riV1JYKow3LLqVt4M9FoCDFWAtrfmvJLunf/iVr\nA/nT2PpR+F3pMEewUHDYxKkOyN9Psh5OnzGDG+NqRDE+7EMbreqLjOLpZse4\nGhpQ0x072/YQrqj5Wl9TLKhnJwUQ45aFzlGG1VjgZ1E911wExWN+piTJuxl9\nDW+CAFoohWNKVtwaLyZBrtBjtyqSCkVpyft/EJfBh/XaY9mq2V8RzQlWvOuE\nf2PX78zLFkoJnvAOaB5+U+SrP47NaWUwVbvNQqgaclkvkhvLx9S+uYpHkp/i\nZMJf\r\n=9AUg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJ5ru9NK2TGt8q5o0JoeXKKBVuCBbT3MnPtIm6Vv4tzAIhANGl1dfoixZdrCsPFeOWP2Ub1nxAbCUahlViKNTJ9sE0"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.21-alpha.2-testApp.1_1536733269520_0.2448929946747047"},"_hasShrinkwrap":false},"0.12.21":{"name":"teambition-sdk","version":"0.12.21","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.21","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-KrBKpsslapWw+M5R/kCpWF154b4m8qWniJJyK+2whXURA8u3F5bOI/+WwR+EyI+ZOIPoVgrpt9SwaoziRB1xuw==","shasum":"8a8bedf41fa971c9c8f57a1ea4d6c7a9d051a0c1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.21.tgz","fileCount":371,"unpackedSize":758666,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbmgEdCRA9TVsSAnZWagAAcDsQAIAQQe0RWKoyIUxN69AU\na628MBm0OSgCukS0tHkkdJKagrFYelR6nu810+5RwaCcS8+s597eMpFTzfQ1\nyz6c1xPuwCZpZjW8cFF5wlatBe79GbGVvteNPLEd48ArmnN5y7Z5JESKJydL\nLlB3vQPiW5r4PYfS4RZFwbVcwWTbR1qW6zN8KfcA48hMdrhq3zdXnNvanuTo\nGsAqP/dt84PD9OuTYDyG0/ngzWUl/YvJVKjmVLZwCcPJc5JZxFh3kxX5NC67\neeSFITbEbOsfPSxMeY/6bnn3rQ6+keRlq8vK18CDrv3C42fKD6D3nTu6lT11\nYLTHPT5RGE1Ba7L8RbdS5bWAFMXpcop0xI6EhOo2JamW9SNS90wDhM2EJOoT\nT6S3IaLD2D7q/ZMTp2bzn6xT+mEK2kyTug+i2vnGst09SAEA2Gd4hSMH0Vrx\nOHrf8RGJxpIkORqm9TNqzm7bPXNoFiZf26hWvLM8uB65mUuBJn2uYqDFArvw\nV4GhCyK3u8clUE8DRo+hxVKxO+pYUOp+0uDmVjUzPZz1MaqYehXTcMFqe9Ig\ntKV7u1RpUId7JiX/D2095RpTqJQQNrjUp4F/QBTeig2QFgw7CCp/UONYih28\n9FNryTgEoeYpEs2Wy0FQ5QDCf8aZ5gMaXW/hHEkEIFbLV75yShtbU6jJibwO\nLJYK\r\n=V+rb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDPqUyNdQI6tS0Xr2rACa9xFc0byVw7dw+VOqHHY9RdCgIgcs8xFlZAoWxPfyDnQuLXJ9r/ZB87u2ogbVVnBdvyqQM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.21_1536819484450_0.5942482579941344"},"_hasShrinkwrap":false},"0.12.22-alpha.0-taskdep":{"name":"teambition-sdk","version":"0.12.22-alpha.0-taskdep","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.22-alpha.0-taskdep","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-qTvEfIwDQ0MQrpUi+s4LJM/dmyUbUWmLUqG2O5r6ZslI8dvRYxrSicp7PtW4mYu5UrB0gzGTstelFmyFoEJxpw==","shasum":"ca66b434f8a8fcf46ccd14a3e72419d1bedb65b8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.22-alpha.0-taskdep.tgz","fileCount":374,"unpackedSize":762032,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbmgY+CRA9TVsSAnZWagAAMVQP/3T5Y1eMnt3NobxNM1Ux\nSXtFSzBoSO4GBU5+8kDN/FLHYJP9SVH7QJ5M7P5pKGsJULPLQiQkKsmPE9lX\nqs+mjJ4har74mv1DgocNdwhqIxl8UJSSnpsyqgJg1JR4QJhTrZhR2E2ZJyz6\nwYw4Aif+zaQb7m97gesF2asczRSzgj021HNPv2lyON/z3sDH30BD8RYSiw2+\nX71bICicSKoPSkGvRx58hVywRlETakRCdmHW11okLBg2CpmKSdthFNehv3hy\n36r3BkJh0X7FtfENLfS9s9/+gjBpkpwljJto7xYxw0dd6j8bDB+RiqAYGSAQ\nbVWqMgOo/Y7OmgQgZMwQKvPFH0nhLJvAWXHPggd2i81KskXyxmy3lX7tVrY2\nRmkfCX8fI6Lw5+NxhDJWZMtobpt5sj2ks7yAeEmAvZdm9wzmjthdEekG650c\nxQQIMGlbE3jca52+x5o8hcY6CPCTUzvu7zsOFqHKA3QLzL88fGc8h8IQbQlD\nbYzU4zEE7zdVU3k/tSLwt8JvwSsj5uEbOD47GwvEf1OO13qcyFqhwdziFHPc\nsZmP+BsHsCytusXiMrDIYDqVIlqdYHbaEkswBcns+ZyAPjcjm/GwVxRRefAt\nk6kWAutYf87jZYDx2Dy3eoYl4tslMAbMYTaL+YODZc9e3ZzVtAfy4fBIUVAs\nEXKw\r\n=HEuY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDbcS/R85qdqxzpP+pDpOaJ5z+rx8V4D8Y7aWlDg+D71wIhANSMvFEwBIyEJdFFNFACI/p3hTjKAhld57y6BHJWDUXO"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.22-alpha.0-taskdep_1536820798097_0.963169921589839"},"_hasShrinkwrap":false},"0.12.21-alpha.3-testApp.2":{"name":"teambition-sdk","version":"0.12.21-alpha.3-testApp.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.21-alpha.3-testApp.2","_npmVersion":"6.3.0","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-JVLHKesyBIDcxJDmZcgRXRkE7W/MlYRNHzUvRJ2rIOCiu4QSmLZ9UdGeLkpcG9MqtucMCKuXKR1eYsET/8/hLw==","shasum":"4c74e258e1b3a8a4c95f7b5f5d426af89991b45e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.21-alpha.3-testApp.2.tgz","fileCount":380,"unpackedSize":778550,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbn0LkCRA9TVsSAnZWagAARtgP/3usrSbu65u58AgjGM7n\n9DcmUSTzTfsY2OvkVyRXuiS0va5nw3wCQA7lHl1nXvwfgUPi+i4zFlBA0Yf3\nkJKzvTq34vtYeaohE3w35Ia1Wyl+19BsnzBlh8G+Bdn4RN+lBYQbtpX24l9Y\nFujyUWiI78DW+gkd0c/cOFfLUgsXpd/4K0adkiyAZzyPJzpOi0akvUBinvio\nUXCS7FD4XODqIjsewqLm0JkW8IR2YnEhVgV7Hs2JwX6pOuw0GuSxU7DBT30V\n4twXAMiXSygQ1ziJKQTTA72uL0IOXUrJz/GpEkTqEhRbjVaL7jAjEc8lYs63\nvDDu6JA2Hvtno+J1ghaTc6bbageaABZ7XcBfCflFYEXZDNaKDkJYL+f6b5NC\nkXqdU5A/Lci4V5UXoak9auhd0oU6yPzf4Yr94z5kdl1rTudYtZ057MwyL69Z\nEuhWY9NgfzoEo1lt5omeAVNiu4ObNBaZsrSvXKnFajJ8G7rM1TywmKw/GTT6\nWPGoZ1TpDCe7fEQn5HMJ1HWR+eZ/ACI4KcmwQiSMBSflKNI7CIRzRw3S65OY\neNLBZfKTNdbvf7Gkd2UpKFcLLRku+fVR0lhQqpCV9Sow2L4Rop4LC74E8e5u\ncoeNnxauk5gF+RiGCewA4qNQz9BcNVRNy5PsJkgjAOSVZcMs3V3ePM4z2ofY\nW8Ss\r\n=tIog\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCYDAMi+lCnIR1z5WG3d8xNeQbLIqMPXKGRpxWywDjPMQIhAOmfgcGqxGd7A7T8FyUKcgVZK7/e2b+pjpQQjmup7qAf"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.21-alpha.3-testApp.2_1537164003053_0.7115613707134751"},"_hasShrinkwrap":false},"0.12.21-alpha.4-testApp.3":{"name":"teambition-sdk","version":"0.12.21-alpha.4-testApp.3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.21-alpha.4-testApp.3","_npmVersion":"6.3.0","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-M4L7Lb6TYhTaqcQ0Ich3It5l+WDbFgkS/s1z6DtQvCiPiiXPkbI/2uWIORbOLQiogGCcSUfShCtfDQMw2liXBQ==","shasum":"7e9365dbb73e46396495b788769c5526484e21cc","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.21-alpha.4-testApp.3.tgz","fileCount":380,"unpackedSize":778775,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbn3YICRA9TVsSAnZWagAAYowP+wRCJ7CgqAVu8CryXPP5\nUYI1CzXANNqvnefn0sHf/iGw9zemx9W/FmVkOXLuQrRL4hQVMglwUxcFiftJ\n8RuXr5Pdpx35xdkO3zPynMZIYWF66wuHmtm9BfRkc2KyIvPFv0tW494w++TH\net2beJZzhN5VTtYXpHSJfk/Gw2suW12njScCTjMp/BQNb/G70twO0HOtJzJV\nHmTzDWgWYj7DPGm8V2m6HNXI81FpcXNbsVAYgMTvm9DIj0w8ZHt3Z5V7mMLJ\n+efu/vYg3dGGu/ufdzxx5j5gTRxQfnHWt8Rmbsn53PbHpGlrRI37N+UYrJ+o\naHFCIRcmUyTJUjFtA0wzB7V7iY8m2WwKA9A/S1GFQ0m2wmiRbZNFZXANImnk\nNkQB2mS20nkGksIjB+818qNd+GeEPlihDr/xHacTRfkUt94YTaHXPCLsVkX4\nWjrKNQABCA1Ifosl+AFlXO1PJrNuvffGd7J10jd5IstaXNP1UD97cgtP1Bsx\n3O39gjkrxDkJCqX9L5TzScPYCO7R7pxPQmAqFwfqXdIjaW4yJmo/fDTu29wv\n99cm8i1ynlVTuHU/DSQctmNU6ZkV+c/AmnmOMDruKl/leRpzjtuISl/Tm7gu\nMdQlad/1UH83Hmym/dokHdvyAwy/DxaLkktOgRjtaL2tqFU7Bd5fpZR3GLmr\nYSW0\r\n=1l0I\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDcMZyvwHqtgG6dwTDxalWFcTAOKGodKY65Whd8cYxn1QIgdcxBC2dNeqza8nNZV02WLmtKXiTAIWZVkvacPFOY0iI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.21-alpha.4-testApp.3_1537177095266_0.3957841200351315"},"_hasShrinkwrap":false},"0.12.21-alpha.5-testApp.4":{"name":"teambition-sdk","version":"0.12.21-alpha.5-testApp.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.21-alpha.5-testApp.4","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"irinakk","email":"irinakk@hotmail.com"},"dist":{"integrity":"sha512-AXnF4Km0Su/A2VPYINIE/c7OzCGShcsM94lO3o1LJR+nl/MS66cui1h6vfx6SHZS6P2Qe/QQp5xnvH0PxmcW8A==","shasum":"aaa0028f3543581679cebfb1a1bbc12a3d5b9b26","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.21-alpha.5-testApp.4.tgz","fileCount":380,"unpackedSize":780574,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbn4EICRA9TVsSAnZWagAA6yQQAJVUv9fhAoIBCas3SN4a\nXtDKIgTgYQMwl74FYbnQSwXL2b3UJHJvE2NI1n5PJXXweF91o0fCkAx0jtjO\nt87EShpAiydQx2ghTswJe8XgTLVHZMMu1/M3EyKqGfBRCfZ47YUXKSMZVdeS\nNdecOp2royS2Ogv+vLL9k6kUAAZSzFbCU6wTImpqBJ2S6/6HdZWBWleqfmeW\nxy9tY6Z5e5dQWh8hp3hB6g4BSzR4ZrIAGGgmfkkvgeQw+Pz3kIucwKGjw4IJ\nAkyf69EqcZZ4xOIbu5BbbMZbvZ4U6WVPRncEZFi1CCjJfR5W5KCliQ4QEhiC\nacnyevK1X+vwFh02Y8U09jNSYYLRBOr3z42n76iY2l1DZB5l6nOQO+mxKN91\nCOmwQ3q0P7lyAArFaZBoqL24P26aX4x3FGvJT8p9SZgiS5lMcNghvwzb6MnI\npl6GdIaXOollG2fbwVEwaH6Do+Ttc7XkYxvXrcJjgbQt7oFAlZXOYqnnnb9u\nwzxd0yvbWOsfm48/1L+o9OiLCPwzs/5KamYNMq5QVxUD/AShMad6VMJeGR3c\naRBcvH1KqE4a6Y/CiqhYWl0JgOocWT46ucwinP07qNK5zxILjNEPYgmC3Eoo\nSae7fVgJtgd1Mb/xvbgKlGl/ojTp6OGs6PS4wTyhzqve3Va2l6ZUfMBSG3Rp\nPpQW\r\n=iGCz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCys0vn5qjE4iaaCsxZ9x1qxT3bxNNU97ZYpebLzYYhxgIhAPFzaj85b+bI57sAclzjRHrVJY9aAsiZSEcYFl2y5SAn"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.21-alpha.5-testApp.4_1537179911946_0.8294832813524284"},"_hasShrinkwrap":false},"0.12.22-alpha.1-homeactivity":{"name":"teambition-sdk","version":"0.12.22-alpha.1-homeactivity","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.22-alpha.1-homeactivity","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-j4wilYiXFBgNLXKzMd1FzWJfdCymmyuQBf7bYuODBBuVYB+aXV6FHabpOu4LoNgLhgQv6/oRGha0rDdYugDSXg==","shasum":"8858694d6f1fb238b2e6c2cf1818548830640462","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.22-alpha.1-homeactivity.tgz","fileCount":383,"unpackedSize":781214,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbpM2jCRA9TVsSAnZWagAAEwcP/3I7QThCHv9J/8r1mcS+\ntRp9ctsiO/1feoQwqir6ReeH3Ql/ApIIoptCTzX49UBsqwDgg4WBp+P9L6kU\nZ9DteH1wWjNNPOYbVKSrjAsD3IxkeTio8JOxTq1kR+yEeUwt39N1ay5hgW04\nzZmQRDPMCzRHv9XNrCsMXvEgWhhykL6EkOcBuT9RGoIi0cfdKUixocRQimkF\nb+yT/Mf+AOWOINyDPVt/2b8UwYSMvRh1xYOAukAzs3rPF+f6xQmxM5SNbR2a\nvrmt3Hl7FSp1tARo8oxnKETu+WS4FtPlDDxwbCGBGM5VU5QuEV828MARJkWS\n3wHQYGrVVZDikBmwKeyaJvKnxIXWCBb5oH++g/wyRPbsWUxIbC2J6rej66qc\nV/XJh0cS110vTs2GVy18y3KAYTEdCadiMNCsRWlIg6B9w4DBVDXXXcwQFssh\nN41SpyU94cyX/emok6z6Ha/7X0IBdSy1bOjdOzUkw9ZlXwTatw9OguIgn1v9\nfdl4+gVWMelbUqj4xSApbGZirywLflTOwioROPS2XU4Zlswh8tphBI0hK14w\ndVjQgIEZ7k3ZqpCREghaL7L3+/xipiJi33FkVVvsGrfrwyxsFnpuGNJOYZN6\nukOvdFtXN2OpmQ+Rv4tJQQYnl49iDOgeHwZlpQPkeXQG0kGik4tTts4A+i6V\nt8J9\r\n=Lnxn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFW+ecNBP5zVreYXoFZHc0uLPimH9RYR9NXbTpuaXjx7AiEApEz5nLOTA3qSR/1b8DBggx4ay+9O49AqTTWqdd0xvLo="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.22-alpha.1-homeactivity_1537527202297_0.8050634952431994"},"_hasShrinkwrap":false},"0.12.22-alpha.2-homeactivity":{"name":"teambition-sdk","version":"0.12.22-alpha.2-homeactivity","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"gitHead":"7a5757fdb04c165367ad025c60ff4b97b9c7a463","_id":"teambition-sdk@0.12.22-alpha.2-homeactivity","_npmVersion":"6.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-ZEq729Ade+u+wFKS2P1KeuJQc229T/azE485sel9/zNgSsDLIRcm/voou2iavYE3RSqH1negUymGQi2GQ503fQ==","shasum":"f66a65c51dc44ecea29cfb3b9d26d9e5b19291e9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.22-alpha.2-homeactivity.tgz","fileCount":216,"unpackedSize":834729,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbqfW0CRA9TVsSAnZWagAAvzoP+wYAQtg5GCjfGeJeQfkM\n27Hvpzw7TvFcztVHqFI7WogggAYQD7CJHXJ9F8qq3fGFbGrfA9TYMueu5QZ6\nA3TnERSaGHXVqZe4xYfOF0UiS4OX4YJr4UzafmP2oI+zl2qiWDjToSIRmqFB\nQfNmeXEj8uWb/NYnA6amMUf2rxbEJRKTc2nmvBG+JFgVCB7Ooc3DfN3CHG/9\n0g4UuOZSuJZYKwtYxaTyS8Uo/mZ8MfSD6CNGPnjgE3YKYqXBbWoF0SVt2UE2\n9Pwu+g7apjwjPxw+ZGKY9iW7bZxZVZ5+JCwneOXhmNfaj+F8EgQuRTC+B5qX\nobNA3Gbr/ocTfAnFaQSZQ5+4J4wL5wG10TWmjMGwUwYRDExKdsT/SwT/kDJq\n/IhlIGectvPHKvRM22+zquTASVDDtTDBdWlKPhv4bXdEui6VyNZEuzHR4+rB\nzD6tcmlpUEqOCt/29jwMuVJg+O1Bho7UjTVqAKzvDVXHHAnvlz2cTtySYBHe\nKqkgYSXGCMTQNcNLqwwnzpFDbB6EmEJJ++yWboyECRTGDjKai1EMg0t8j0ww\nFPwEdtJf2ri+zFCZN72wJDG+GdMc2+9NM8GQqvG/jxXgDZrilSsliPbevmuq\n4YzC55XpLrO1nZ3FntsOEUXWSj3nv3HW0j00aE5sDrO/b/DRmj6/FXE9r2kj\nB5Wu\r\n=/3Nr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDjOcE7vZ7dZmVhzOZXCsBAhwHmL1LK79AfIUYr2U0VIAIgZLTWYrNaQqvfOjvoWXgF6FFD6Nm1AK38aDVY2hcAe3s="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.22-alpha.2-homeactivity_1537865139888_0.0231264688395747"},"_hasShrinkwrap":false},"0.12.22-alpha.3-homeactivity":{"name":"teambition-sdk","version":"0.12.22-alpha.3-homeactivity","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.22-alpha.3-homeactivity","_npmVersion":"6.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-8rId0NdZ8Adr/EZkMZMf3LtJpGuVT3rQjsK2dRErwzNPNG28N3/LBUkaAse9T1WbQae4ij3WZeAI4WNZ5mCXuw==","shasum":"a825a89e0f0b9452f586bb39711243d28bd3cdb7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.22-alpha.3-homeactivity.tgz","fileCount":383,"unpackedSize":781579,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbqfZ1CRA9TVsSAnZWagAAgrQQAJSjqaSKvxpyaOh7V/Mv\nVRBOYeGwEhh+QoORlOsIpsoqpLzzSSyGEpmgj4sGsNJpX51Cu8fbqbNvQNIM\nH/eeMz/Y8fTePDFNCW3vX5VPTnvF1+cLgrhOTiSObe42aQu2qSGpXp6ppcH8\nCSTKMruT8TIVq6u/nWzIi84ERDiRHZR/kK+E1tSXK+09UJxDg0hHGysr4dzn\nfn34ETlbQYI9uwKSxr2G3vB4CSoeqmHBQFMvxs+zxBIMtibJsa/LuHl1F/Ux\n/Ffs10eRfPqeqNNmxq5p8Kd1ozLKGxbo/17gchYpS9Z6oyAVCLObCtcyppj8\nQWhI+Ew7s0IjZeMQ0taEgqVJhm74boP2a94OJDyFeyagOUHnQKPAU/Koehb9\ndCL3UPxE1VCj937+BZOMJsteGq0o+Q9v+b99rmXwcgBIXpJgGOZC93FMcC3S\n2BIKUETSY2a1qA/4B3U4VL2IRdx8HVXG0px5qk2GyYShfrVk1E6d3mzmB9I8\nw6ISZBicvFZwB6eaVkfcBee9fNjZRWUx4l1iHaSQDjfde0pQcZTYCw9PXSew\nEHSXZzQ5FL+q2lLwGJdlrVo4IPtMzDB1IWjWDDfloFobtdevV8eZHn4tk/nm\nUhFs+9lpfPl6uR0VC648vo86JOhquwL+n58JRYNBrbTFdeZgnlm0Vna8zQsN\nhhXk\r\n=+zq5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG4+Fz50Xz0lmTqWOSZkODUiEfcFWDwY0QefFnjnacsrAiEAwDzztKDcynRYXKmv+0UnK78/RfA8Kx2LYrhpejMVFgc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.22-alpha.3-homeactivity_1537865332846_0.03466952682520685"},"_hasShrinkwrap":false},"0.12.22-alpha.4-testApp.5":{"name":"teambition-sdk","version":"0.12.22-alpha.4-testApp.5","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.22-alpha.4-testApp.5","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"irinakk","email":"irinakk@hotmail.com"},"dist":{"integrity":"sha512-eK2RR1H/aU3z8MWWANeVAxaL4VnbNQkLXDszYveYzrwHmQPo4jNsmq+Qfp6iB3sgjzpjW+uTMfntIaakG6c6GQ==","shasum":"5e79294a48cdd230bcb4c43769dbd380bd2e7a99","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.22-alpha.4-testApp.5.tgz","fileCount":380,"unpackedSize":780869,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbqgVhCRA9TVsSAnZWagAA038P/0LbNyZtayrzk8TK2Hau\ntEwiIIRLEzic6IPJ0VOftPGd/c0547tOCL8TqD6YYOIbXaVpeKrwChZu7pZc\nuq2LajmmubRLxGlu0bnp5cZH6pYmlUppobLQCL81XONyfiF1vrZTkz1uYSCF\n6bvUQnbvNdNN8ZANIFE4Q3ikKNPuH33Ft0dkppoyKrSfGkL5+47U7a+8Bi6Y\nM6xeLNKAkAMW9MhQxBu5Mft8XMnN5S9293UlsTPF/rA97BFXqZVg3vyjoxEP\naUWTM7TnczR63W6Zv7+wPvLndQ0iIectuA00CSkqmUvsh7d1KjKbjKS41jZt\ngi6BE2KWAjPmVs1qEJKxfIGoL4E5MeAL25l3ZWqKX9apHk88N+XWlyjAUZgV\nq+ZTJYvgTKyfbKFlRlcm0h/deybuPyiVDxkWwHV+erc4jdUzcYFz0VqGqbWG\nVNiSs7e30nk7EnVgFERj9dnyGFcttpn6ukBGDraZLwS5xXo7vt8seqS7bJ7u\nGgSyZh/1bWk5U/vN8M2qEQu97YCG7ZnL7Hyd5Ik4ZfdpHeaQhNgLQ+FNmgmL\n3umJyoYm32Pwju7rp+JXXjrEZ1+69UaGHaPmEyCGvr5V1EXSUC1sOqbY8xnm\nGnkZJevubD6amGWmtaf3N1lCyrBVeVSL5M66sOK62bIO6AcIb7Kcs1Hbhbha\nASdk\r\n=FiXU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC+ZsYeEzxxJTS8h+jQ+SZpLDfW2u5PHV33x7f9BsGQXgIgNX7aidZZUQEHe0sPlYjMvdT/4+WmixRJ6WUiXPoNElY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.22-alpha.4-testApp.5_1537869152441_0.6889033185769518"},"_hasShrinkwrap":false},"0.12.22-alpha.4-homeactivity":{"name":"teambition-sdk","version":"0.12.22-alpha.4-homeactivity","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.22-alpha.4-homeactivity","_npmVersion":"6.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-JeyFCgyn8DMZEjfC3gn5xAGVP2gd40kYNhisrZIS3MA6MYzrj6Ue49eTGSxneeHIlu3rb70oI7MNpWKl7yuqTw==","shasum":"9f309cb94679adbcf526fb0302a5c2daaa0d67fd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.22-alpha.4-homeactivity.tgz","fileCount":383,"unpackedSize":783104,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbqggkCRA9TVsSAnZWagAAbqIQAIF8mtR9+vPiNRdw2SPU\nB1hxsz3afdU827Ylty/O3h4WX+gcdeIAT/I6nqMoSXFjFra7JCeCiWlJMmEa\nHLSV6yffeJxiLyVfEJ3yKKHWeW5Q+HLPoi0+HWOB0mmkkjHtxm2a82Mg5fze\nW4comr+pdSQ9ZU1XOMI7noHE3x3IjbFERE2UmqnWA3/giTDllxUDsWHsYH/H\nVRUW5WHOvMlKECB+Tuwa3VSk4OBkIjw5DIK6gu92BwufRDWuBo5nWtzVLBGc\nlX0Esc8EqTbPdw3pxfCmCTu7lWOfIxiQQ45sx8kkiDrZrP2liLKhyJA5lzIH\nbPSi497Qjw4iX3A+CMoGdUZ/wIvRi9CitqgfGxa1fFKFuDeyS6vjPI2SXJTX\nxXxGoy8Whac8wfALqD8HhEY2oZHFdoWmevSipmiXb+G5Ldgx+qqBzbJyvwcw\nRnfhMgXQ4aal1uZ9jtJzQLMWwaCTWenCaXiFjT5TrlxMz5Z3VnqpgCowdxTR\nTxahPLbFPbswFOU9gZW9B4FVNWVisUTpACa92YWm5VE2oixxixFaOH9mlk/A\nmg7SSpPinh4g22WRDcBQjd/CK/4cAno1/uHLjqAIciCg9YbqCSR1AzQIypcQ\nWixQFSNJnAGlV3pPrDiQi82aO94yVLCiazF7gOk/+24B4ae/8DSQvYbf7ULI\nk/kD\r\n=0ELs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCjrahDzZnRFdbzDtpjEAEkCYVfD8LZKMvu3UMC+m57MgIhANFyLWMZFh7jl5eOhMQ68ul6zXgXK2HHDS3d8HEPO9VH"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.22-alpha.4-homeactivity_1537869860001_0.5938762816913055"},"_hasShrinkwrap":false},"0.12.22-alpha.5-testplan.0":{"name":"teambition-sdk","version":"0.12.22-alpha.5-testplan.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.22-alpha.5-testplan.0","_npmVersion":"6.4.1","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-UwNb8TTjCD7utDn+K0FZRyKMAr2BffVQK7Sbf7VNtEsiXJvL4qTDD3Oflsq7NJIVjGvorkxR87kdXCC4utlw5g==","shasum":"8d07dcc961cc3127aaca7a211b36897c30c68a3b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.22-alpha.5-testplan.0.tgz","fileCount":380,"unpackedSize":787164,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrGJACRA9TVsSAnZWagAAE9QQAINvFe9g2oz1aUeeDEal\n/Wgh1nSnKnT7x45OGfmCmOv5alAGJNtabuzNRBD7VxOl7ibEnYPkoa43DTPr\npbH58kQuoImbGTyZx3yYP+fvfWGFIW43GZnCB8+aRAu+2wHMdfdcusHlW9dp\n7CXg89W33Gu8mkzvAkcztKI1rxqJhgMsMYgyFmTVD1p07qYHBps63w7p0+Ny\nqvneG49xtt25eh3Voq6rvIWTL5JM+hWYn4hxsTImYz4i7feIGghRv9xoYq6l\nuxDjRxd2WsmKJK7k0mas7cf9t9daXC8fdadQwxHr8xoK/9GXnjP8eN+6fGp6\nYgkAwJONlid6iDUs0A4mE0/z1CbZsemRVvr10OQ0VmfgUDUeEzmifZUP9jyA\nKIFcK44NRpabcKS2VSkXEBtIm/6eQcxHfO2L9Qi4k+Q7Vq+xO1tekG7jd6MN\nzMsNCN/EQ6sfhe+JegDiShF011GN3UDtJVTm05sgyBMBwR62Lfz7Mr7sNGw4\nB0PPNfeQcRG+cNOs6Abg20JdGtIl1+PNtMrrmdTpxWup6x5eig9fM4GJV2SO\nyLdtaZ9up1racLxfxgGwJ/kthgfPboS1kWVawEZJavsjM84iAdx+mvclunp2\nhMdNCWzGfW/sxLG5ozjLRwguokUmt8heEetgNKn76I60xziAdydLZE+lIxMs\n99R5\r\n=tusE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICqErJr4MbZ7ax2Yg59OciiG7oHtLZC7luf7h0odlGaQAiEAzdOZP+6x1nN+2EGAAujc1NLuaOHz2H93Sk6XypIcIt8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.22-alpha.5-testplan.0_1538023999361_0.6813234465593734"},"_hasShrinkwrap":false},"0.12.22-alpha.0-graphql":{"name":"teambition-sdk","version":"0.12.22-alpha.0-graphql","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.22-alpha.0-graphql","_npmVersion":"6.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-Ordyj3gpASBfg6b0YO1Kd9CEwLW+aargLExyOoRCiu9SjPmaDl3J85jDaP7/9zFPv/Vr9WRlbGkzxyC3PmzBDQ==","shasum":"895caf509110e0c139744a9d3e66d83736ef1588","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.22-alpha.0-graphql.tgz","fileCount":371,"unpackedSize":769981,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrIPkCRA9TVsSAnZWagAAElMP/3mhI3LmHnTBQ5DHbhY3\nxdfbaOFRQjg903aKljf//iOaN/yc89tx+OwKh/qhR/Boz2fBFKXse03H7wMB\nAWKrl1Lo766iu9OS+8DaRRVc19Z3s1s4JX5svt3h+vzI62UCtic9xJusNSfT\nIE4raFEnOsrSP/27GAXQ4Z8B7hZC8A1LTL6pcFKHIkCig3jKcpStau/yrrau\nZjBTHNbD/FO5CW0npdY7VdodvD14h9xvXST4qpZyEnIUOMsi2y+Y+SHmdMKN\nhI+F/0D6b0smKtPy2/iD33sI3OG1Oe3aZl0CFOUGdcs7Vr0WHwJyuwaOIHQ3\n9N4APCkwmwyMhOOyaXHBeItdDIabuiEg7AX4As/mke294pi2JzJnOHXDwz9K\nYfaBYW+GfxSdj0tHEIHYXOT9eBoNcQsPF/3AJ1PYlop9m2sGRe9i9XuFJuE9\nmqwBLK/tcZjyDXqkbOVl3h+7obuX3pvnAnKfyTUxd0vgCMHWNaZudoqMfeHy\na8oZFdKMSBhi+idhDnNCiTbpB3j6bfJk1/yqNqwsYBvTeMml9e6bc5mz1vc/\neWv6tYyLmwUydDXiBwVeewv1HmvOFETRAc7gmnYgL4vA9nRep36ZkKG1D/x7\np5PvrWLcXG0xTZ4b2Tj8FaObIiENGgIikQShM/G1aorWaIHVrXA+XRUxykwp\nnssy\r\n=PqyP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEZqB8nkqGB1GtKywvSEQIANQsiIQcWWXHcSH+t5RcWfAiAisGyJjZITFpf0jG6IOfv93golAJ9BTxMIIJCIdUPPJw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.22-alpha.0-graphql_1538032611991_0.11124700524461617"},"_hasShrinkwrap":false},"0.12.22-alpha.6-testplan.1":{"name":"teambition-sdk","version":"0.12.22-alpha.6-testplan.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.22-alpha.6-testplan.1","_npmVersion":"6.4.1","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-ZZGT1Eps+NhhAOlv2S/PCCvPRljYQNMRpAaQvbCynjyieZCEKCxwdjqKxkUbCRJvHvzhV0vj32Tbch3LjL+0Fw==","shasum":"361db1bf574c356d667a1275b688ea1cdb3d6828","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.22-alpha.6-testplan.1.tgz","fileCount":380,"unpackedSize":787633,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrdj9CRA9TVsSAnZWagAAFEcP/1lEiX3fr8jRjBjL4uzp\nFxd5nJG07V0c1ZxW0qNDkt625p8ZtzTs5Wv9ZuwqcBKXAZ4KRhlB+CndwhE4\n4SEqyktf2CQLGKnFSO8n2tbne69uAnUakOYqs6qrKR7wpV47WQK3B1e00nrG\nJprqEZ9SyZlW9eEgOcn5+oVbJAHMMAZOkHpeyfgxR4lAiICzZ8wBoxuyS64d\nymrB87zV28jp7gswRSwGIX12A0OQ6KnLTjImXL8bz6AdMpAdfUR0qcWEIxip\njzPPGfgd+R/WO9Pn1LyJ+chzBgENtqmFPHdlSm/m0xgfYdxa5IoSs0n1VANc\nTTLY7CCAja7dGuhrbJusDNuqRe8HZ8LQstbfm16un13GXS2Ccw1xHr5iJaa+\nuBLahBaTA5lVLe18cUqdycFMNX6AsWd/UB34GKMIGu8h5ZfNmyCd1SSIphv7\n8Gh0jxzkzW4+Gh9whLtVZxrIOUzA0ksTqsOvTOA06NnAVgpm0fAOJwPH1Nwd\n7IBPNxszYoOdgSBgzMJPMPDPAPtBww1rxxSQvIPXNV7BzdngArJi92PHaPGk\nga5noi7m4XnmOej1grHMmf1K/oXZ0N9pgoy8DFzO3NK8PIgFyiTY7m6FVcrc\nc5/VfmX0sXQdtaYOORCeTiI973shUqoZVh7+B8f35ZKAd3noE6ktdT/wXIov\n9raB\r\n=SWhv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDFjxVFv9lb24nhZ42qoRsa694pMKdatXyQsmiJA7plqQIgS3YukWuvDNxyeSdyEQAdZNWx/9Cth9oihE+eFE3hPh0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.22-alpha.6-testplan.1_1538119932146_0.7752109783313672"},"_hasShrinkwrap":false},"0.12.22-alpha.7-homeactivity":{"name":"teambition-sdk","version":"0.12.22-alpha.7-homeactivity","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.22-alpha.7-homeactivity","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-jHo3PhbkCezdMPIuAl0dmEiLv66RWi0BnXlqgn31TE4kFA0F/ZasMSRWOnpgil0pNgKv9rn2csA6R+/qpnmLEg==","shasum":"0cb7792c1c178e838fc40667c938fbfa6fd100e7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.22-alpha.7-homeactivity.tgz","fileCount":386,"unpackedSize":792146,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrfpKCRA9TVsSAnZWagAAL4sQAI4gBYbyjrtxmNr9F3/U\nU26iXUdlCXoTlAJV4+UXOUNTy/F5vNlW9/YlAdfh6tiC/24xHt1wKUmrDsV5\nzLDFGqMaa8YEH9M6ZLQzqmbuDyVxD5jZWOceh2b0I/PJnFgJOPYtiA98h8hB\n1RDTz87aq5I9ke/aTGO13n8lQeyP4LS1dCqa/fZ0ZVs/PzvqlRQcOYYGiQnH\nZReo0xNgoLy3IIFGtJAli0FFiRnMZvsTY16uxg3pQrKEQC3mu0IGpwKtUz8s\npgUtfD74aVhzh9R4iD8acKcWFuuFWQg0F/4FMYfgIMyDWKrXVDbq0WmuJVK4\nuAurINYT+crri+wxdp5UdpVrzbBcdVVT5ZQgIzl2m/MDZ+KeXyTE26uQcEHh\nkzBnsv6O0J1lMtcq13x9S53oY9PNwNXTDtL8qa9BJAd2fo4HOuJhvgjmlYnk\n2w4IMecpLcGqGlsaMBWILyBijGjRp99R662ySo1JOdl95SKHx/8bJ/9fl+BW\nSXwDFFTH72dQnYlVM+NlFfu09b1oOOpG+B64gCwa/eVDQ9t421PNIcWPrlwv\nw+jTbmkkWiQG/WYLbuKyhqGiBUAWSzgAVNVO11jg89Vof3z8FDxVxwQMFUyO\nqfWt5HSVwOskdQl8cjfbpU9dWsPS4W9/GYTWb/mO76ZYlJs2HL44+H6S+PFI\nVHOQ\r\n=XTsS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBkfk9V/PICM1fA/yMfdSu54d21uhGDROmRK7zGzEf+wAiAcfdN2Q0pKvqUCv/x5euP/iLtdUFCNsvNih5o1cEITiA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.22-alpha.7-homeactivity_1538128457702_0.6905462913888052"},"_hasShrinkwrap":false},"0.12.22":{"name":"teambition-sdk","version":"0.12.22","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.22","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-QNars9dPDC/8TaN0vPnbY2EQ7jblY+1wdA4G49jxtWUtLvFy+qDKKgU0fZdsu4Se14YMKDt2+LY5+X+aDxITrw==","shasum":"00abc09da1c8a6a740dca79e95f737c2bcfbaeb4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.22.tgz","fileCount":374,"unpackedSize":768844,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrgkvCRA9TVsSAnZWagAAPZkP/24dKaCc1L9lQ18EjPQE\nOYoPfbKIkuCnC6SAOCtjk1q8rXeKTctEVFzGJ0AJv3j1XYPkgvLFCRy4bN+7\nYGrAJ49JXkafgi/SLPRir01lZNtLnrcjF1AC+20WR4IyLbD/9SQcXCntF/wG\nJy3pWxpZ4owQU1idIFPYT3RRRh/+0SWqUpl5Kay9qQYaY7EeJGYhwOdq5K/F\noj61USgqV5RZtYNueQJvdJX1DNHZ7W6KdXKYJOygib2BxzsdSNa5SAVyANId\nn9vcOIr1tP1XQTRBGTun/S7ymtzixBy8cVN70AvnFTnBNcvUSg7SYHakIlX2\ntXPX1CilI7NpKmgg3eRsDyVJeFBWmNQ9AuevkApY4NIWf4uwZXnGfdarnfA9\ng6fA11iW0qH3OA824/yzd9yrU622anZM9/AO5K0N+tvGGmjVS+gbaMeAzISg\nzUglt2kY75JknaYZ1rNHj8A/qP8a4koqqmMJMmT/Cojkik1DKaCzAUdiis+U\nQQAPv/39byE5GuxF+lBxdQMczYcAEH6NLaVMzxWbv3QgWPpbPYxShsk8oTh4\nZmI8AROzNOHHm994KhhJMIB9N3MQGBNElK9nPTh43+0ScHD1PTuyeuoGfSms\nTVxHAltc2Xj/UwbX+rj3+HmZPGBQWQoMZ5NTZFgkbFP4p5ZasvwGxqu9N8pY\npGRp\r\n=3xz7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDGNQUrEQw+QmWmXlFzC2vuhBJanFKcCxpW6gPEWo0tlQIgECmziUSS9DTyowgPvkxWp5eloW6Ox47lN9zbfRak0Vk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.22_1538132271094_0.3882212135579757"},"_hasShrinkwrap":false},"0.12.22-alpha.7-testplan.2":{"name":"teambition-sdk","version":"0.12.22-alpha.7-testplan.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.22-alpha.7-testplan.2","_npmVersion":"6.4.1","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-3nYfuAGKq3OFpsncwer9KN6Gpnv6HksF15/5RINQLuxnNA0japC05OnTadnd1FNllcYqnNISOshOkL9v+8URsg==","shasum":"db8c43c950b0e785bb9534b088468869592ce873","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.22-alpha.7-testplan.2.tgz","fileCount":380,"unpackedSize":788256,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrhuxCRA9TVsSAnZWagAAgUAQAKL88u29vPB+KTM5sEfq\n4gU1TUOGgLYb1mAQbGV5uiALm5qDH6pcwaZVoSPHBXEy3dSqBgNe9T87cJju\n+L/bIG3n2K8Iq7zRVcVk27gKFTPjpG63Js4A+7b57wnawfg2BJQMKK2yiqbk\nw12gTCgdynugMSEy7c6gWh/EU4F/bwl8Zo96fI4A81mwq8rv3BWFR6vzZjd0\nQoONLYSTYHto/Ht2Znu0yq3I1HypUolPUhDj/L0o7m+2kUqrc9PZH4rKL6BB\nwgJS0KTs7TU46Ly0/1RoSI6K1lFtSCOBPVMhj1mvhscFFEEVELFSiXg2kHVm\nFCc/Za8LgavGObb6ViwCLfvBeTg7ykRtDbBB/zPuOjPHk8Ka506L1b8q00aB\nUvu/hHt0KAnrxpn2PCcyTTRCmQk2e1k0NtJz8wGNzZwRa1/ka2XWNTXfQ6zv\nYS6INeOJjWPQRtsn0FCLgDqg73B4YL/eFxxpSOYbNZaUOH5YaDIMfCmes7cl\npOLZsqitxIc9a/MVsgBZ3ze5EI3rSwor77VyZ0Zse8BvGfGqIWJdLRO/eLNp\nBFp8WHV7iY1TXGdUZYcVKXbIPyEJEHKDebb8Rp3q69v2DI4Ss2g+cxyml7Nb\n4EnJMMjaIM787vLp9ivrWsFhU3BZiESIyBY+n848V61UUExmLrdFYF4e9Vf4\nb4II\r\n=4D+7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID095vMdOvRO1oEVbP3JpILu969jJ0nfz0uyhuW/dFtpAiEAq/0iu3hpc0iQv68nD1qUsykH6cVWaT+1JBlh7VSkpC0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.22-alpha.7-testplan.2_1538137008419_0.045491061704533875"},"_hasShrinkwrap":false},"0.12.23-alpha.0-testplan.1":{"name":"teambition-sdk","version":"0.12.23-alpha.0-testplan.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.23-alpha.0-testplan.1","_npmVersion":"6.4.1","_nodeVersion":"8.11.2","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-ikxx8eSBWGbd5GcPnM2z6eSgM7J/HMqYkr3AhtqvwKGzL7A49wwpRiRC2JR1KUkOnc6PrloZigLzalpOHLhGIA==","shasum":"61cf1a864fdf1643fd344fc9b1c4320d6dcefdf9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.23-alpha.0-testplan.1.tgz","fileCount":383,"unpackedSize":791430,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbriQbCRA9TVsSAnZWagAA4YgP/imX+YGMACzstik1lNUG\n9964yFb/Zac04rXQjFG9TyirJNCtMV2H8dInGdElLGXn1AJEQpwn0bnU/Ca5\nVwFbjcE4CL86KEPckkjvBIm61HIjyjeuVGFT5IPTitlVf8AI/ePrAbRd1iHU\ndCHqn9eyJuScL/6NIrXGc6yhjWdgFtGLsTBBtVrH58Qo+HDa42+MAvqEbsJs\n7z5a3K5hvNsPFLIa5trgd/hbYkLQlJDNhuUrAVgkgFDKciO1GoQ2fM4GSj4n\nMHDwPJ2LgmyBv58WeOIqsxEQ0puvZy8GLTz9u6to+nYo9+r1h9hEg1QUMiQg\ngLTi0WAF/5lALV2nUChLymkzq2fWsWhCstuN0W8sj/uPxkhGdW7l762A6gTx\njTZQDbSUVin/n18heiYm1Ymoz8rto6VuhDRZknppgftOWaWLRuZ1ZsG0AIDg\nIfRo3se1z0QrkoYOOtORnII++Fe6SbLO5qrQNzIL/y6RYb/Y1O3/U0Bg5Feb\ntyn4AvwFvWSnIwPa1ssWOctVIo/kZgILFpehvwNmv/dJlNcy9poQCdBC2VaO\nz2ZN6tdaD3m/oF6rnztgN9Cg+qVkxlLzm5Z/b8lj4ZWtaS8hn9NbgvJd8pkg\n6Nexdkc85GwnFd9oDvRYqiBh29HKPEA1zawDyvlzdsahYBUe5mpeVc3ca2aA\nU0HA\r\n=yepY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHUH+voJxMKfz5vPOVYoYahqD4aiK66iQneyFQxmMwqwAiEA6P3Hrr9MmdEltBVOObGiEtPpgN9XEBnBPSaHyOqoNfs="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.23-alpha.0-testplan.1_1538139162105_0.20333332936211002"},"_hasShrinkwrap":false},"0.12.23-alpha.1-graphql":{"name":"teambition-sdk","version":"0.12.23-alpha.1-graphql","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.23-alpha.1-graphql","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-j8sFcR2SlprwcYUrmI+FPfQx31FbRzGVoE3mEIEiKxxngZlm7FjAoeqIuph268JGk7lswYnPfK50AZS/5OBF6A==","shasum":"34f322c977c232daa55651d2f4d2c41fb64e2fa8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.23-alpha.1-graphql.tgz","fileCount":374,"unpackedSize":773331,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbri35CRA9TVsSAnZWagAA3/cP/38dTGTW+ui5GAg0SGMj\nQQq7XMVa21pTdZYSS9uk9oTP1JD6t7+HrzGeiHr3ScQUOt2ImkZF36Bqf6/B\nnaS0PwtW4iU9XglB2XoXm7WTnp5hokWa8iPaQXeK5qEnkqxlyePq4jyJ60jy\nZQD28CbwkSHwJs+ZEmUAQ5FFQu2+35bDkYjG7NhtuovbvPD8gwNpFOLI0Dxq\nx5PYSCmuh5brMWr1OEDamcVlsvOVVP4oCn3DOe9gmIMX1aqQ8JTU6+WPLrvV\nqhnHdUYShjqLZ+ZRQA0jEbrXDhJfCk5vcilK2qBiNDaE205XCF4vGxRPHj2P\n4m7+l166hFUTRg7aRHbnW1jEmZgR6wIdm6YTq30eR02nDJuni4uYmM9ancp/\n9YQSftuX5nyYmmFih+m1IA2a8uWeTnbRosa7gJ0F9vBQGqIu0dg36GvSbp5d\nVqbt5y8wSw7wMfL5l+dBEOTmEIjf1MsT59ZTF9OO/ujlE90OVbNXEXLcGuce\n99wB692zi+Mj0AI/nIUFK9TBf38EJ2deIjw/4ls4u/reC4uf7Y66NYoOgeon\nRV3f/G+YPafina9h3eHUcMlS9YuvBxzpFPCqAFQFnv/QspK35AvXKeXdvsXh\nvWrlJ7kzFbKzJ2NGNqavr36/Ia5QIdkY7Tsqypi+5tP+HOuY7wa7u3MScsgq\ni9F9\r\n=AhYX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG0e40vQOAtuT+Wbc1T3ZNK0I8caCIA6kpyF9TH3ILKKAiB/APFBUR3ZhTG+3QASXsBmqvlzmsAmdG7zAednOR3m1w=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.23-alpha.1-graphql_1538141689090_0.79425957312405"},"_hasShrinkwrap":false},"0.12.23":{"name":"teambition-sdk","version":"0.12.23","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.23","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-i44INUufnF+eazMzEXR01OppaJ11yNduAQ7qCWsKwGebp0D/qY1SedLva4IvN17R/0tIXXv/bjSpTj0FNYEMBw==","shasum":"838edd94ff2c16ee66454f2cd85a30b7c0fc0667","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.23.tgz","fileCount":395,"unpackedSize":819163,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrw7WCRA9TVsSAnZWagAAATIP/RU2PK4hd/+7Q7/nd3hS\nnczroOzP4ILLccRipfBL1+EWk2UIJ3UHveF8WYpZePt0LvAiROuSe8gt2l4I\nPoOxpsA+3iwn0g2wK4DfOjuGIAQOK6G6bMscInoxKsA4YKFz/KY3VNgLMlx+\nTOLc7OzoxgbSg0XV4JWSCixBXoHPF4O6/txWrnJW0v30Gkq2nigDGendAZCt\nVpWWmHGex2opwsqcfZFm6xRO3ofwkMn1inpY9Aqx0MWijVuJDBOdcmq89P3c\nkVmMDkPwIRpc/mBdaRYEqpInF8uCKWdSXjukKkLzwjWQ1HfUeGHr2Z5wv+NV\nK8jcrN46CDD3pWJjCJY8igDIp8O+pQ62UaCmz7El9CF6/GHwKigmtqZeDb7M\n/JIm6IXrgy8FlPvLTOYgPtj2VctA6ReG+yjIkAhHlZkmpnPlpOH+EbVvsDUk\n7rfxUMljp2iaU+NnV8lE1aZS1SKGfBVKSxX1imvEefIBgvLmMdqfh1HSJlyT\nAXEcI2Xsa0+ITs/NPciLb+v9FIKEJeirFnhCGQtCG8RpceLkB3y5lkpMbVRJ\ncPnqvy6xnvK36Fe0UDoQo3JZub34vTCLUzjLVQzHaPVTUqWM78qyKbeXjKkS\nkQ5ZDDTwmLyuEM1xp23XotDt8vG+vue3qlTlX6BEdIlsCDuSDEl0ETFmAeTW\nOKcp\r\n=spQY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDu8PL/9HIYriYwTceTKYNg6UV20ZPlMQJ3i0LBuWdLaQIgc62i1uxp9oV2GmvDoWkOaFb2iQC1LtjuEKVLdEdoZz4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.23_1538199253507_0.6223304567054242"},"_hasShrinkwrap":false},"0.12.24-alpha.0-testhubbyorg":{"name":"teambition-sdk","version":"0.12.24-alpha.0-testhubbyorg","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.24-alpha.0-testhubbyorg","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-+Y4h2DgfeTAGNziKBNEEUmBvZ877aajKq9lAWYUokjJa9FwaFQsFKD4rJ1Boo3qwaVnoMNEXfsGL+Q5F8VggcQ==","shasum":"0d85237ee16be69e1883e261871b53ba242a6ed8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.24-alpha.0-testhubbyorg.tgz","fileCount":395,"unpackedSize":820172,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbr0XVCRA9TVsSAnZWagAAA1sP/2wjtevGVUaIUWYrZ5B3\nDVIgfCwWLzv4xTYzgDPh1V1uny1pEimtMdXLHcSkD1FSbnSIHWF4rk6AItaQ\nhK5T/iKATBIU9rS/44Hiu5vTfCSkQ7982Gxur9chayw3Glm33VF329tWwOh+\nqVfk3fkyUi7D2Oo2hlk7T1klGFuvxWrKphqP/qiBfRqOtXeh2pXLSuRoRHUp\njoxAtayQNC5nRr46W/0D3M1yQVUhL1gLDea740pnfpf4kEcpY6jKoMxTxfeI\nxSCXsaroD5a68FFKZZlUDN52Qk1u9Aq0XQNzpjCnREYaR018+ShlEZ0/N3Re\n9g/Z1WZ7HeO2wtnKnTvgBZ4S3DDWREbRkdt4iLMM486kdJ8EqZPTx5soH4hC\njNJfkwWfk24en6TIjNY0dxOUuAhJfubInglKTlvy57MVKlz91Qp7ZRUW+Tpq\np3o7HaLY9vQZ1gSMKgmterMky0PN4gu/fqvr53HTFHpqx8VHsz7H17OJAMy/\nfJtGbJ13H11SpyikkoN5b1nEzrr71tvo1aZWExVKBtlIAbN3ig131kwpES6F\n+fAW3OlQJC2jZ4BBjXyh6PhjgcLo7cfYiCkWKQBFlNYtQMaroDYCfBrQ2AmQ\n1bqNr494LgjjUW3g8fVZBz/UIQdiCsT+KRwBsfx+1cB/yIkGIz9Jy6TwFpoS\nPMpE\r\n=3B1o\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFWt0P2Ohby5uv+HYPBRKN9wXB73DO9ET0a9+hM2c36NAiBJKWB8Hrh6OGGKAULKrFFVjzxrV6GzSoDQ1AQ5hxBEQw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.24-alpha.0-testhubbyorg_1538213332840_0.3624847975842098"},"_hasShrinkwrap":false},"0.12.24":{"name":"teambition-sdk","version":"0.12.24","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.24","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-MqZ14sHBKrkMphoxDCNr5TmYemvojjsluzh7TS9GCwwxskUjlqH4bgJEl7eQieIlAGIHBL9QXcf44IYzNTyWfA==","shasum":"b5683c8bfb3d079cbb32ffa46a01a1b6a008b846","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.24.tgz","fileCount":395,"unpackedSize":820151,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbr0jbCRA9TVsSAnZWagAA76MP/jqiXxiYnZtZ7aJsgHiU\nqskWgNZQetX2Dy3JGj53/+4B3btFFGs7D6H+x64mYGe0rkOJNNvMphO5765q\nKKTiTRstfDLVOleP/iSx1tNmBmD1XOesKyJ72ezJolrxaTRzWczkFq/fdqWN\nBuIyP4rJ6F9zto+SISGUHoyaizzTKEv1e9QJvxNkqwXHd5NRQpQlVURyNofm\nATFFq1s/ZLd6hBM65fNI7FkbLtLh9cTQxkZS+swcvuD27yUNWWXIk5tZfPh0\nAHwMjx+VKlJodoji8OWccxuUvjuywEgU7ut0BBZArlw4J0+wFihkEjQ/OSbw\ncIgfEmWFNE9b5g8nf4oS6vhoXXk9c42QNcyy5LXEMv9B3/KYDLNnOHlNub5p\n04SMi4YHjSZP/R1n4fXVu2Zjt89xhli+BYtSo2VsN071ZVXib4q+sG8k53gK\nsygUPWhAG4KTmB5YBVA8vUVeoVyr3BIPTB9wqUSeBS87lVybu5CXKDl7iFrb\n3i2wzKigNAkp0udAdY/M95oagpFtz+luxo7jJzUk1Dj7nuS6IaXgqAt+xbk+\nFnEf3Pi0SybuJ4OpnOzqYoraqLNdeGruQQd3duKWt4CWx/XE3CLmbNydfarJ\nMXuIx4OZsLIpk0jbAcyT3RxfcVj2d/PM1Q7wT/Fub4TIZDVBoNMPZUGth4mx\n+SYO\r\n=CkUN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGTAjpcAH1LmoLBGvq1dwk4MVDqz3dCb6YgZXGFp2EVtAiAfUv/k4h4njujSp84ZYqLzjEmSfEuX73ope9R9w2WPRA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.24_1538214106191_0.4651046197596027"},"_hasShrinkwrap":false},"0.12.25-alpha.0-graphqlerrors":{"name":"teambition-sdk","version":"0.12.25-alpha.0-graphqlerrors","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.25-alpha.0-graphqlerrors","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-YjuszVCZPrJpF/ITfVPcL1PClc9ZR02xW8j8q1j2VbdfxlThrNQ8GvlMpOxB8wxZMNSG4m8XO/l4/OGaIBZWnQ==","shasum":"5f27c72e20d8b638c7108a62818cdf599ba5d68c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.25-alpha.0-graphqlerrors.tgz","fileCount":395,"unpackedSize":821817,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbsFnmCRA9TVsSAnZWagAATt8QAIjkHu0pD3uf5GFLlbvn\n1coQXT0NJMXaYpC3HNIwUL5QEpXi7DC7hJYCinGL5txhTFqs+XS5IwwrzA+i\ncd9IbiZE4jsqXq9IKQbbgwICTuRoXIUIjUG7XaE7bX3tUoCgeh+INlB07oEH\nzln9IUUe081uk3tPciymJEDOLuph0DHfRM7uIldqbVr23mPz6/Cn2XR7pogv\nPODXVCrrzrEXxE7lhsgirrN89EyhaKJoDedoFAYbfWdUEgaiLqQFPlN9LWH5\n+RYxuFAYQhdXTj02VXb4l6c427lV3fxG425eD0izfciY4aHKzjscnW63Aygg\na4Ab6TsSEAJchQE6Mx2t3zD8TTcQBEqeo5xR41wMFiP8lEfBXp5TQZs50+jj\nYXYrZqr0wuD5z9CWF2HCqQtEYfIwZ+2FbVr3pcir2QqC7zUyAp6f/rZnm+vn\nVIiUukl/UWAOCyn9vmvQb+EyOQFuIKMnRAd3l7+TRMmWXgEF02V7IkC4frRJ\nwmqK2JghFTL9P11HrzmI+kyyN5V9QNdiQRLoOZ8Sfp8RTdnGEGuNN9GzWUXD\nEQHCPFMAEplYzAHvegaOn6Flq0OSC3ZEjPJn0ljJGpukJUf3FYuL+cBvi3Zj\nJ9JnHVerMh3/vGv7ZbAUzg7UqbZH+XdNZNhY5fO5AAKAZ1qggjemGU4GZcDf\n+eEI\r\n=RNwC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD+IJJ5tU7RX5JCF1L80yPs35sb0lBJfef7cVM0oI/6wAIgUx7cNoOoHe8IAVdLfL2Ah3frfnGrm4Ap0xFcZZwtdX4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.25-alpha.0-graphqlerrors_1538284004938_0.9028193276069216"},"_hasShrinkwrap":false},"0.12.25":{"name":"teambition-sdk","version":"0.12.25","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.25","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ivVOUYcfIfMRLYV+rbymu8lsvL1EdawaSKXDERAoj150fEmtcbdpvcikxf0fkRdvdzGBQ+PULXPvpxc51CpyMg==","shasum":"cc8be98b90efb0df6f0bb978c507d88aa143c928","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.25.tgz","fileCount":395,"unpackedSize":823145,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbsJJwCRA9TVsSAnZWagAArz4P/17fIBnvQ5orKsfSMgZo\n8HYGOzg12EfJZRqOVby0vtg0Vq1gVA6d5z7Sd4IMEs8CbvWw4LwtuagC0smg\nW/S6S1KVjKymaDgdcJCoqId1g7ZXbNy3O8RpDZ44iV0LgnpDuXtl8HTdwpj/\n+CihqJCWE0TBRT98d+ETFLXivRooX6JDlqxULXzoy8jRcdV6rhcs1wvlsGfY\n8x+ebKM9iDNn7JwWQCEl2RTK3NC1g03kGtxXRgGtRbwLYOCNQSdxAqPdOa4o\nk/aW6hR1jWqb0S2tWF65Cbj/cSttIadoLKioYmZPfPvuirvK03nFZx5joQxc\nYmoZAAA9HQLE8rbUKX4MNRJPYXXEa8yzMvgHlfguPC8EelPNRTdA3gtV4ptb\nX+Cgb7jOFb2fxrj88ep1wv7CTOTjUtQPtkv6SVOVI5HTUQeo2BwhFK3T4S5V\nFqcLYnhUqCrOsgPqa/efQLXVqnOEQgoWxAQ2+dfAqU4RdyKuD/PW4p3+Liq0\nDnXdmoEXBznVWnxzbaSWQFT5M4gWO4gVmGe0mTwsd/kikzIFrtX/B7MvoFkR\n5YFgwNF5hT5/Vf8S1USU9mVrewwDCwx84Xz5rQBxNkR3WvcS8vcbgBOuz9P9\nRm2OJ+JJxyBsJcbLyEVGJ4fqlzU0ZDvGXDUMCfzsEyqxULu3MKJbxuKHxBUr\nTNtB\r\n=AqP/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDnl4AlFoYe6bqD3q7VSePl7qlXUf71GyTpp+oSFIsNiAiEAwp77/1KV4y/Kfn2zV/CsrwqhwBBwA/v3LN2abCXtMvs="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.25_1538298480245_0.4847391135361965"},"_hasShrinkwrap":false},"0.12.26":{"name":"teambition-sdk","version":"0.12.26","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.26","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-vkUNhP/RyQqFfzz1emQH9Ys+xfXoGCbcu9DSYH0cCydgFv4+qor8X9BJY0MsCtz7/njfOiU35xxN5UfClr8NBw==","shasum":"cccdf3c4e07f1e0506bac23ad94ad92bb0207324","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.26.tgz","fileCount":395,"unpackedSize":823165,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbuxwBCRA9TVsSAnZWagAA3E8P/jo0mfeYpz+3jJXNeLe4\nImMQsnIm32UEN0tUTsXKbsKBT//CUoGhCsF5ZCxTHa5AN/jgXRgvkC+RqF+u\nDB1kY5AB8nMiyQIOJ/vNPp4QgLEzHiy2DS9Q9cD4Xfl1FDusOJ/fpBE+o3Ti\naMrN2eMML3veaxvboxxWpqCgbph/znENKEOeN7NDJqFz4nkZpJ5GA6V9etWO\nmKAlTRt259Jx8zA5voN2oBUCnvnS2c+R87eGsYWqN1cMwEi9pRbWzIOi3fCW\nken3nnvS3Dazml0eK/jBG+RCklZmlhFZLCHazjhTsngs1fbUQj1svEEjeef4\nUKhWoIIziuWtMAoYg11dd9Swc0yZ+DYLR0gSBRlo6CU+scUph1Ug9IpgnVDv\n061A0FM4jFEXn+eUCdbUOHoOJWC6QmDPnlQHOHQUUtT2pQPmlARq+tfV9Nwk\nLUduf8+OEff0g37mS7f3Fht/ZLTmQkO6JuBNGgO0bOczGbu98VmzGe4feK+o\nwVUXjidEaKO/qRE3PNOg0FhsrXtp+Im3Um1A9zRRakxfIUOC1sECr702FF8G\nqSReJ+Aokl53Ie1kwCxZ43j659sJG208F4h1lPFJmOe//1YHy7osI6BbGNDK\nScmik9dNhrGNKMvzamAjV7aT+1P3HFLbO3jQeghXashFB4zZtkml/UD7EWYT\nP72l\r\n=zKqW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF9s7JSbS1UvYOihT3WoX4zRHbTfMCYPNII+yhlWucKLAiEAkjP+5NI6XqhtjyA+nCrVga+LWYFAFrFAxPWEBSrJSic="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.26_1538989056141_0.14528114264616043"},"_hasShrinkwrap":false},"0.12.27-alpha.0-dashboardschema":{"name":"teambition-sdk","version":"0.12.27-alpha.0-dashboardschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.27-alpha.0-dashboardschema","_npmVersion":"6.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-2JnsY/mcSswwrVslwHgM4BNt5suNjTAlp/1dR1+HGrtjp33D3iUaG+wFWx5QE0FQ8SLZDLLqqRTpCwDL2JXCVA==","shasum":"6fe27a2a5944ac1387a59911c5603388688d0a25","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.27-alpha.0-dashboardschema.tgz","fileCount":395,"unpackedSize":823308,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbu3WUCRA9TVsSAnZWagAA/NMQAJeNnhWgmPJbFtXEiYhl\niLL/idEKUuuMexxfcPgNGI78QU0TdZ4V73rEGC6AVUaV8I7yGvx65u4dRhad\nHnx0gaP0of8rRpu5r+L143NjurA/easlqosTdfDsW+KOVk0RQrvbOxPJF/P9\n32f167Ytil0wSD6KB3JHbOD7JlGUillXsfXmlQV+ActhkJZGNb6sLvc6blki\naWeNhSyH5bFw0Ait/SCw+n/Q2cxfxJgkWcPueq2k2QpAZ2JeAd02Ggw+9YlY\ns8CU4ivAZ+kb7+FgxzRpFdH/a22xrkGiADV7hD3Qu8wgSNGje/7LRsxSoK7Z\nzLSU4Ywk6xUbPj5+/65Vy4Q4kfkjyxfO+6GhklNghN0krhNymnr4TSww0Nxr\nnzOb9t6ItPXiYCj70UegifU0Zw4Dv/RCXF7dRI64kABU1C/WfhR8dE1XtDq9\nTPXgk7yAiYtdOwwDJ2xYdLZTH4/ssJBiCc4c3+uX1n7y4MdLARs/ATf8g8Zz\nkoywVL2QxYC7hm1jd7OA641AB5+F5uo5kvOJZJSYtFBQ+GSyuoCBW5WqZ+Lv\nuRCo0Uz1vvziTNPapdqfsILLS4ypCketkK5xVWnicVTIqB8f+dhAV7UOTKr+\nENuluvPiuvk8cem0CHmEB15xLepqU9L1fDb6WtiR3Rsky2fghsN73ef66plN\n3K/1\r\n=kxJr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAQDUgWVWUV0o65DWOn/2KcRGFolXnsFdFkHwCdcfPKhAiAoiXVgrOXD6fDZLKCqkUEvpIXvq/jWyfcb4iZCkZDetA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.27-alpha.0-dashboardschema_1539011987210_0.02602395600178764"},"_hasShrinkwrap":false},"0.12.26-alpha.0-activityteamstyle":{"name":"teambition-sdk","version":"0.12.26-alpha.0-activityteamstyle","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.26-alpha.0-activityteamstyle","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-aQ2Wm8tBcWlL4uSofM2BdQOXpS4paLqSEpueCVmBrOLd+aQz0ViYGFNJXyI+tkWdYHtDEhJ3oKK8Kkk4sn5bRA==","shasum":"302dbfc643ed0f640ac855badcbdf9b3b714c79d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.26-alpha.0-activityteamstyle.tgz","fileCount":395,"unpackedSize":820197,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbvBszCRA9TVsSAnZWagAAHYcQAIpHctf9tSh8OhNATuf/\nCmcWdnnGusl4D26dKiotMQbaA6rVnJRqlVAaCic5AEo7+TkNMF4ygM0tEuCW\nujY1tdLaOPhmT2uVG9TDWIgnJSBzphMaVR80QxI551pT9gOJn9yReIS726X+\nof+JBPXixhhI/4fFlto5KbERtC73u7XZUOyLzkGQuR356p0TdCA/CtFPcOHt\ng1QfBQZSaAXO09DEocGGhmSzZogxJvBXroyLPKfn4wUD6KdupJEakHkLykZw\npuV7UO+IdiKdbVN5Q80vzzshQRmnuRPfQ+LHKiA3yG1Far25DJbzTXXL867d\nqxi5dGmeJXByQDp98D6yIIL5517zgwQp15wYq1UFcGIqdNXF2aZdLw7guu9l\nCmHFuOeJsHuZDMphOFTb10mp5XfkU3q2/JZjzP2Yonc+DVUMjSXkdQYX0r/I\nQzT7MLywV9VMa8S9UlnifMtDzkOb3KZWRQJeSTyAJlDUL7oASgmcM0C1m0Az\n/5kTOlOK5htQN5J504R7/FFurQwYo53snF3DDikdMmRguTGVhdaam7gcEyfI\nm2gGOndNx1GrJ/lu8QgKrwNHuFnFM3fe8pZOPiy39OOmzQ19hjgA+aMYcufP\n0RgtwoQkmmLSa4phymFdRMS4sPtjny9jYIaQEwp3b1rWUlFTavAEaf2c8cjN\nXCBn\r\n=PX9C\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDVdNUM2+ASM+/USOPW/j7iFcYTTA9GWtPX5y1dZCpVGwIgbDFdERAG89kszieldW2e/G8bydCXtZ+xYZgyD47SEjw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.26-alpha.0-activityteamstyle_1539054386401_0.51673134207459"},"_hasShrinkwrap":false},"0.12.25-alpha.1-teamstyle":{"name":"teambition-sdk","version":"0.12.25-alpha.1-teamstyle","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.25-alpha.1-teamstyle","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-uPEw1eifqSZRMLmsR1/RzDc8M1YT2sVCwoVpTr0CJGt4tfqZpbZGy+GbRDVoRiqwXUts3MPGo9mBgNsgfdmJcQ==","shasum":"12b25182a9471f312bafaf66e00808c32d355680","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.25-alpha.1-teamstyle.tgz","fileCount":395,"unpackedSize":820189,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbvByOCRA9TVsSAnZWagAAhmUP/2EUSxFM29mrn7PXezGc\n3aE0GW7HNo+gSgHgcaldC2Kgqq6Br3RaYEGReJzi5Cw/kVrXEUlJXMZ+kC82\nxS8jkzoSXaBlpaxq+h2u5QM5Vc5Kn92EJEN0hVD9Qq1vtQINi8lnQstpYeIe\nMi+I6u6RSqJ0M6kMpJOWt7LMorzpp+BB78ijUiVtGRqeXyH60u7v1QYhytQK\nkEKylcNvdieHfaq7lUvETXoKRoGEzaP2u/Z+cCu9kujPIUj9WQgUP+2BpGR3\nRAnyrYJuxetKA1QchYykeodcO3FtLY73Nma7SGCxQfm3DX/VXB7ajNbeohhu\nkZ5UC4NoGix+UCgIK4AfJOKEvUFGhwHnIcSqkUSdemnnOvaBGRfeNkBTuHXv\nTH4aqu0GerRcyZiJUJaHeHdNbHKmX2xxOMiTGkn9Rx1mqI98mXKxeqNntaZ/\ncVye1Xt0m6WMt0LqNYRxwOkDS8eWI11xffxIhAN8/V4uiWvp4PcLLeKjoF+b\nVx6wpsmWffdFh1JQ6+3iTnCrOh69h3k8c+3miqdl0eQz8m1xmSE0Z/Voj7Y9\nYTyEiPV0chJHaCUdx1LqvIDkLQys0alPbRScfhITiuJh3nPY/iQ4ObHlhcwP\nKCwcaz3JlB44+yQAc8YozrX0iYmJA58MRfp1XHaU63u6altkhmh1I+YM4pP9\nNcWC\r\n=ivin\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFdCC1vLiMjsmEXbiRls2K1eM/yOE6vq7i7vAZb9zYo/AiEAj25A37xXotKFF9/qoXW34QKaxJM5YuGgCkz6RiDCTLY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.25-alpha.1-teamstyle_1539054733995_0.031415162088071824"},"_hasShrinkwrap":false},"0.12.27-alpha.1-role-update":{"name":"teambition-sdk","version":"0.12.27-alpha.1-role-update","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.27-alpha.1-role-update","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"dist":{"integrity":"sha512-kS4VV5Hr2i7y36txRHBovU/YNuy/uKSSaPrHoJOD4RRtixhvQF/ME0EGqsOxNwYbmg3iNJlMH6VBl24q01zTBg==","shasum":"35b740311fa9f082d7c30a96f37b73eefc60a246","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.27-alpha.1-role-update.tgz","fileCount":395,"unpackedSize":824152,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbvtH7CRA9TVsSAnZWagAAGucP/RdQWW+dX8ZY60mdpllA\nwL+zZdjsHQ2t65zU3mCPNpeOiPnnmS3eThyZMp8OTqmzA0kt39MqlBH/Sc/e\nf6aQDQ0Z6zvdGj0bhAEE0ek6V7x9kKsNYYwbQYNY7PjWLZixtuRLiTSKtIVj\nZjLnz87/HpTxdAWvr/ptmk368wkgED1/UmQhUNdGiMC3lWrPh2UlCiJVQVBI\npPQGRyrbrLfzTb74x2E+v+nEeqOss1QV54M5uFSP+OkjFnctyq64suySN2J+\n5QPn6acoP0pKG9rUE50zjTyArBlR9fVP04mmnujMRcHaQYfHqt2cxOm/aSfs\niQX8p8cN3cFgReK6N+jrB9z+uhENq/3GvQejXcHftLVWR56IYij6A2GQXJRh\n0RLoUTGNvWfQvWXcmXvrh0KRmhXKlmbVMWHG6ej7/K77wgqkkgsJaW8vyI8a\n/gNEZFnR94Upct8C0vAl0fUGwxyxmsy9jQuuYvcI/Y5FHrxbepfeyDlNYsYE\nLw4NWOMS6pu8eB6nouk2c0HHKQFdNB2mkCpDIyaoZ+oGYSDnEOrV36IVDn+U\nK1PNBzyAxkmCUQ31pa5Q64FRV51wUJ5wW12nsH9PCUEQATrVAz9S4z37uOGj\nDmRZDHOHioW/JEj6pLWb3k0StX/12Lot7hq+Nxyl0f35JDTVOSqpQJRKP9tI\nDqkz\r\n=RMnA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBcgYcLkMM8ZB+KNuM7Ce1PBAaEXXN4K6HQXIcI1OKGCAiBHCgmsMNhfdUWKxfVPc/ygOBTMQjh2/bIqr8hssPLZwA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.27-alpha.1-role-update_1539232251025_0.30703615832873776"},"_hasShrinkwrap":false},"0.12.27-alpha.0-project-schema.2":{"name":"teambition-sdk","version":"0.12.27-alpha.0-project-schema.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"gitHead":"e1f276eb78321db518e006b1502becf3f2845ec3","_id":"teambition-sdk@0.12.27-alpha.0-project-schema.2","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"dist":{"integrity":"sha512-1dFFfGl/dqvC58P+6Z1mN0GC5H0zIdB5QwAs3HmV9oe43gslrJUVED7PZ8naxCQM14VqD4XGEojxx1lUAVS1Kg==","shasum":"142a9fe97bde625b98a817b6c8d1d5d558601395","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.27-alpha.0-project-schema.2.tgz","fileCount":220,"unpackedSize":884853,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbxA6hCRA9TVsSAnZWagAAKgwP/0bIgmKzsC4ci87OmL09\nI6gieQ8DQy9aFrXwWSg4fFOn2kOG+O8JIo8KwDg2pE6XIFAfbaHN19d5hLHT\nvWVGpgJKThG57kGudainWhpvuPYH62PopABvh9aOIel1zF2JRG6QrHBzoMxI\nkMDT9ynv6ASeiTw+9fwE66z1/Aji3G4wCVgdBiqvANoAZ+IVXk6Gunx7p1yi\nsF9lJd9fAray/HxtxlSc1KeUmcOSZhp+RdZzlc1F2iwCL11FNwR1xBes3Yfs\n1bpdY7gFzraMo4EKJ/qxchnPCsO10VrVzn+1WR/cJJ5LriLFi8vU0oGsH2HS\nguVqzKqP4Va9i09F/FKmiCMQglsE+GJey+2XxyAsRFOqTQwVwXavlrdTRwit\n44LDJLe3exvtPn/QtYJljHCesF6Lola65yZbGro72a29buJ/N1ZOOTfeVJ6B\n2fLHxHPpan0hkiNTrx0sfI1VS11+rHJoLGrh+yR5vA39vtrBAHH/euFuU5vJ\nb2aJOc3U2n6a1i3409wzLkngqEiua8tg/xOWGDOVjivW+jDPtyyXnVETfK0e\nrskNdqtOKDeji7GaDq8mkdZDet+AJpO0Bchh98c6n6v267Y7wj26RWKY8wtf\nZxLaZMo4n0844/DWoYPzxlQUV3pIXecHUCOIi8shpKnB7h+9/tAOMXUeyoTl\n54gO\r\n=o9iO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICPnx6vJjh8tyXLsHKuuYmj9/MIrl8ME7bhIzYwOsna9AiAncQT8yS627tCk5UEiLjxr41QPit5tWZf83hqi0gULlA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.27-alpha.0-project-schema.2_1539575456923_0.8090264120484338"},"_hasShrinkwrap":false},"0.12.27-alpha.0-project-schema.3":{"name":"teambition-sdk","version":"0.12.27-alpha.0-project-schema.3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.27-alpha.0-project-schema.3","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"dist":{"integrity":"sha512-WKdkw5VPHhzT3TyGrWnxyCBVY2/b2ZgYFNC3Y49VGn5iwKs4PvjQpbT7kfipaquzeu3tOknFw3MMFxkWJPie1Q==","shasum":"b0594a5d7d7749930914261f08e1ca3a7c807277","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.27-alpha.0-project-schema.3.tgz","fileCount":395,"unpackedSize":824564,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbxBKACRA9TVsSAnZWagAAGFcP+wc4l9Hx/nLFbKqT0jM7\nBLZaIypphaLckbx1yVogQ0TeZAsVewbBCTtagsQX0z6Y2uWrt3pQhb1RdH/1\nFWSh1tzijY5XrbSLkwO7HbxlwlbyXuKUOLG6GPookf0C4ruvIcW63TZZ4+P2\nMlGQwQAUigNIf/L0Dl/Df/lXuriicHcaueMzu9JcGeiByODexJ+latdffrG+\n2VsVpI/zFHygQq8NTkYPjzYILYCXZ1H7ovPBVwDFNQbm+9OBxSQarInIii3y\nOdJFSkAVr4AnyCobU4f/AihWA+b5ArsYj8LhOqtTcQKoTm7NSIznPBbYmQMs\nOLeKjbMgZV6VORZE3FhpMvrQBF/pVx9s66sXkxiPSM4CSfC5e9b4CccjApYK\nJWQjD0m1fJSsyawcGSMG4Zk6RHFN+BvPqGkK+TRLQ0enZ5V/zOkXpm2blcbJ\nFUesA+rfHyEOdP10xuUIcGiZR1BDqA6rFaiDg0gs9ccSGuXi0ZzuyNtkgWAq\n/Y8xUJNpPhuF7yb3nLTmGefD97IvvaW0wAgjeQ7jR43C5hIqM99vo6dn3HCa\noqw7HgAewFDhJ6qMpXyAkT5BFp47gaVbH19ftSm+DSMJvTKqbWjsffX+ERNH\noP/godnoOo9OvvbBzvqHN982+5PTGVq8/SBYR8sztRjsbWcMKwVC5+K4Obg1\n2ntS\r\n=8AYC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE0WzP2OULcasjWxc+s381t3tUTs6+dQRzFbeEHJlpO8AiEAyRPcFpm5wQueqCCHYKoVmw/vpVdODvWPaKUhQmGjxx4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.27-alpha.0-project-schema.3_1539576447812_0.4258743151382911"},"_hasShrinkwrap":false},"0.12.27-alpha.0-project-schema.4":{"name":"teambition-sdk","version":"0.12.27-alpha.0-project-schema.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.27-alpha.0-project-schema.4","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"dist":{"integrity":"sha512-RPOsbadvEW4ghuKFuetlbQ5n/RYekJvVJLfLEZ8iVAkeDuaC5vRPaFPw5W4R790hL47RhQl/Pxasd/KZFQu5uw==","shasum":"d44d3d0bf69188a971807c40c1a02107329ca4a4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.27-alpha.0-project-schema.4.tgz","fileCount":395,"unpackedSize":824564,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbxGVWCRA9TVsSAnZWagAAvWkP/264p2lPZfADalI5UmUI\npsfEKe9uCI3W5jsW8o5hLJivxgS8EpfaPqVIgtzax/8bwgNmYDEXmpx/oDwB\nvcPSD5LzT9m2wfIDh355ro6nXtIekHmtM02JNQMqaIN6GhGkCCSgv/VcC5Cw\nR5U9eiC9Z6jn5RDdFg551NXNDKnOQL0BwkauCDxNsTOB1Je/s4dxZD7mKl+l\nkkZZI/Gfixr+v9kJIwlae8Oihum5lsYdY/kyESPrsESJjp251QavzZn9zaH/\nLaMEMpYmGL9iHnYhArxkvFapHfePzpUn6achPZxesb8Ii4POcnyKOj5roUrp\nOku6x5Ws1tMaI22KAK7NWB+NGEfzFrcFMTz6MV8soy+Bu3wVesQovMOmQwQR\nNcryxeG7ifFAwoC1l19u0MQed/XUnqpBetmyC92R+/JF5Sbu0MeY0A+kyEii\nHLam4PGXmjBAFZv8gLAArhufFftUZsSeDJNBpASA+28uOhlLYaGDfsS9OQJL\nwd4gwOcwj7/RPBh1uaRmPCa9Y/JhyPSH0pWZvyihttun6Aw7b4b9fiNzOVWk\n9QVYepCSaQr9NKZSwJc0IjLK9nxw/5kDWp1P4iCijWv1B41C9M8+4AeQbQii\n7yr0vSlQKuyy4Dh/PqzPHBWP7rB9i55Z9i601UkCxiOnqnafvuOPQqiuO7pP\nmS+A\r\n=NZAG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCB9Hast83tKCza1ZlyeSRFzMIudPjcqx8iHCrFsq9elQIhAN6Z/p1Bj5KxPdHQ//Fle0SG0A+8ZEqdlfcolwRBRyFw"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.27-alpha.0-project-schema.4_1539597643543_0.3292254301368611"},"_hasShrinkwrap":false},"0.12.27-alpha.3-project-schema.4":{"name":"teambition-sdk","version":"0.12.27-alpha.3-project-schema.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.27-alpha.3-project-schema.4","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"dist":{"integrity":"sha512-okgAGGwDwmkWpArz4SYN7UdNYyzNrJwWdC4cw/8zOTcDMdQlIvHOtV+IoVWHjdv7xEkb2MvgtegpYmA0r1NKeg==","shasum":"d44bbf9bed281b019b68821d1214610d6793d70e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.27-alpha.3-project-schema.4.tgz","fileCount":395,"unpackedSize":824564,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbxGm8CRA9TVsSAnZWagAA8gYP/1skvGW96TP11xprNOHU\n3xrqdeMsv6+OF2sDx8V27wh9MfJMN1yRcdiWuoUJHjwymai/co660VYIt6dp\nYbWmf96e9D7MRqx05Lp0+m7W8zZiHwvWuEsIZ+Nzn4xA2hgXa4vpDf9BJlT8\nbYYFfWimQz1+vaeiMMrAvn+9V4hAUCOU/S1THHOzQSItSaV8fjACRlxIs3g3\npeMTeFUyzXy9O7Z2Wnuu+3ukdqAwh5N46a3nU/+VNngnKBnuKcIqtn/z0hQS\nTsQit237Y1ROL9kLcBojqIvwykaoRZkxg+p2vVKj/ZtkmRkL4Bz+YUygtfHU\n94i7pXhVRsh/qlcnhjGDnAz956Pb9WUQSprEdimlgl3KBBIbH/Nt8C4jRgs1\nT4fWmtTijPGUm85qun8CWpqGSjHSppAA0e2HRvGvP1I7U8t+0Iq/clCz4ost\nAbLX7FGPjJaB8o4fzaKVLGzMRCmuWc5s+O6v6ZAnMjx/AKwvu2OG6b4IZZTH\nFIV2TXE1ydxpoPNuvuQeK0dmdfvEYXdIIexnfK0SwhXbYWXPykXYR5ylp/QN\n34iqSTRy6TwjCYnJqLypyCNLLkJm0HQsa+IK3SGuc9txdBAtnHj5XcLSd3E5\nmvQrb060Pfp+Zjydth7q6C7d5YK0mGV2MeHeUU7xR+bdBTTsD8KJc0psLQFU\nq4K+\r\n=iHrP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDrsu/Tr0uOjDGeDjROF4ZwLFRjMSO58LuleVzIDIMl7AiEAtDWT6RsOjONXR4evh5k4qQSpjMYaq+JzDsJpAHVLCVs="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.27-alpha.3-project-schema.4_1539598779318_0.06276607819627777"},"_hasShrinkwrap":false},"0.12.27-alpha.4-projectschema":{"name":"teambition-sdk","version":"0.12.27-alpha.4-projectschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.27-alpha.4-projectschema","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-2meIMV6UZYvcNBnuCW7SosAmtYBv9NKZmL72U1jX8MtDIFhTINB2sZo1CSQsNAVR4SKBuqmroaQfEUSR/3QzAw==","shasum":"b93dca9a816cc68cbd32fbd12dc8bbca860bb8b4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.27-alpha.4-projectschema.tgz","fileCount":395,"unpackedSize":824351,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbxHrFCRA9TVsSAnZWagAA7bMP/01JPysjWlR7CsRXjjGh\nDO7nY2aDaF7aH9JLFPEz2hGGq60JUpwekwYk9M1RPrrvGtSWN9LmLmbcae1y\n8apFVik6udXUEDp0WJM7b2s/IVEpfNNm0q86Ir3QhJiXeuqNC1xOb8UuGraC\nrGHF7V0T+ErTQR3unMvPW//G6KyKDxvgGGitExuEKPmsyNz7ZYW68p9BVg6Q\nYoTFdKoTrwwjUrNCt1Tz8KKmnNBTZS+S00p9LyWiaJWMHjws3J1w0VJVXB8g\nFegLde0rJblY3+9hFmwryJo7GnnzPbkguREQ5GzBkoLVfTW7Cg5Okzft0mB7\ntILgd+aaH2XU5eGmLDRyOLNeSKZG5d9feAUGR6GNQfSDT9qZ93Tgw2vxg9/7\n/C/I3QdTTgnPtWdVNQx7ygBW0IimTwfIGozZDiabq2wgRKGc016Uv7A9tVHU\nCKYLv80X4ViMdx8UHZaCtQs5fKp3dz7XyZDReOBhdTeKQMgQ563qnic4hjlq\nL+4j+GRmpa+/mEhqwfhrUGYjYV5rvfm/yWaFFrJzvPM2IvHqr274I3nhQHyH\ntYdqdoxe320royEoAQ1Bz+92t4bDWwaDZ2ZWD497wKfMAzejSGrDkAHHE2Fp\nOUNOR1NzV1dpTXiWhiMtFSm4TiSTMtLA2GgPur93lOxBgiCav9xs0hqLMxT0\n3CrJ\r\n=CqhM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFWLy2Ogju160ntkzM7h0VGgplFFbKqjoEF3RJfSjVaGAiBvYhEh+RI3GRbrnNX1pEFQT+R6Ym+dGwkz1KF55YAbYw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.27-alpha.4-projectschema_1539603140272_0.7528628666818205"},"_hasShrinkwrap":false},"0.12.27-alpha.5-projectportal":{"name":"teambition-sdk","version":"0.12.27-alpha.5-projectportal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.27-alpha.5-projectportal","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-yWXYL62DAoSwLoV+OoSd14V3xKG+g2CQ5QKCXGQaqtItGlUIeTtqfxWARt9YqN5xFgVkTCWVUNQ1JyYuUcbw4Q==","shasum":"a1ba295f1c1aa1267875de7283c5cd731dc35c5d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.27-alpha.5-projectportal.tgz","fileCount":395,"unpackedSize":823769,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbxJVSCRA9TVsSAnZWagAAThMQAJvRAd4A9JhXvheUYRfq\nSOcXlLiG2OFeNZqfjJNc3d/ZvSl1kuVg5/TwxelnyOZhYptX4Yin/i4vytQP\naff0yb0WOCTQPWNkuGCiikGjC57VNMRUvoRDxDgninIBKWcPjvZg5387zKrP\nlpNpaudyB36H6HOW3sjVC+rV/NGsxTI13s1UIEqcdRoJrKTmBNIHnI/xiukp\nyKIGNcOay0Fg+Njk1R+GuFReuM+dtlSH0U8IYP3wGBu+Hl7XEnzxLqp+ZIhM\nPDlQENNpe9KwsDpeGy1PHbgBPOxNzrb7su3zSNEHaJgTm8oQChq2sUFH8xxg\nR2MfDRAL50T+DJ70ovaM9xrVPmacS9GvgZgw5HUzyJKN+wG3+R/xYlQmPzLe\nzPDsIWWuyYxYcNr3kQv7Hbdg4P5ealITQotaCT4UAKuzVbBXr1vZfNpYYHvp\npcY1EiHxTgoQLIgYyM0TWMvE8yoB5+0+TMgqTNbwUDG+kNJv+EGg60Kq6G7F\na97IcDi2jND6sFrjEf+QcyQrA0K0TehyeC6J47+HjDlKrH7clsTDLwgawwys\nbCggYwhKV8GCoVvdLqeum3eKtWDULW7BQpeMnygMNIwHJ5OSsBfyPuS+bvma\n0FaeQVlZbV3Oi8fM5QyrTO8D6QmliZYNO6iajkUjrFSxesTLxZQvKlN9ymBm\n4Fr6\r\n=B6nz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGrr+E0iuAp/mG0ZXGKmyCdGdBpF9baHRy/NuA1YUCAuAiBlFzkfU6KkAwvRzZ/JP0kSI8vwKvx8gUAz1hmv/rN9Fg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.27-alpha.5-projectportal_1539609937064_0.5708328357609684"},"_hasShrinkwrap":false},"0.12.27":{"name":"teambition-sdk","version":"0.12.27","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.27","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-zHPf6ihzYfrkBKst7GVRKYsey6/hk5SD5N1peFI2Dq2o2FoYdBFV7jYBY75c7lt1+2Nh2eN0ZlrpADP7zq9feA==","shasum":"b6e46eb863a70d8ad677ac62af6423c072e40c7c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.27.tgz","fileCount":395,"unpackedSize":823284,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbxwuXCRA9TVsSAnZWagAArG4P/iRVuvGDd18mNKFyeBzx\nuu7Yq8ONgNzcPhzeGWdB3PAmITvFRhS2216TBmc/lPQLjtdIp9+TSrLRe+vO\ntV03tv2jQZ3hawBMGU90lwpRRpvS5vf16UYBhJ4c9GZJwLwNUYWpHK/AFlIL\n6J/PIGSJZpPnFRuWTfI4eaMrrvZQK+7KF36Szlx5twjNLwYxNXkep00emcxW\n0IHPK8hlkCvKDzs/lZEsd3wn+XsmVFn32ciLWkgaZ64ligrH3WQGOLjJl2dm\nH2ZFO0VR0/1D76u6J60dtw57HKaf6bLHkwAMB3PF28jpjRxsA8DTYtJYFwkI\n6uNxofQ89ifsUJrddUgKIhtOBE6FWtMDJamV2a7/ScBHN6VgJHlGot0p/zpz\nkqIeVFTw825RhFkWl5y3mXuWsSwKrTdLjG9oZIAUfH/ugJnvsTlUHQai5gOA\nQjl01I1LIrrISsi/gn/YHSrlqrdrRxmxg1XyWUjy7cuUc3fmZNZsa08Om4Yc\ny0WkdvxAiuaSEQi8NiJS7W1LXuqx2Dr5VUB1lz5VyQSPaSxtAHkX/xLZMq4K\n3yzaONsiuKi8GpsTt2DLY83WfeY8j2NwaqpHypigv9FSyzV4dUoMDd536Opv\nQKXsCqYWT9eGGe3V1rYuuv54kN9xjWW9PswgS6H4B+GobJUpAEeMooWXoRn6\nfmdl\r\n=Pi+y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC6/0uBg8FgIW098idcpnxmemV8j866lfg5571WAxklQAiEA1EmTShVoud9nPfoJNa7j0ccsNwaK2EKaPRW8oSqaMuY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.27_1539771286739_0.8235091850647578"},"_hasShrinkwrap":false},"0.12.28-alpha.0-testplanid":{"name":"teambition-sdk","version":"0.12.28-alpha.0-testplanid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.28-alpha.0-testplanid","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-t8Qx9dqavhbQdU+cjb1vvo2BJYqjhqO47qsvoQ5bWY09iT37qwrx7+UhleWLW34qLRy5PtC7KJfTDw3IxvorSA==","shasum":"e6c00b8ff519256f95265fdfdb156d777b22feb1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.28-alpha.0-testplanid.tgz","fileCount":395,"unpackedSize":823484,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbx+xdCRA9TVsSAnZWagAAbY8P/1GshfBh90KtBZdsZ1Ke\nJMz58ovuHJftIbjAtoGd+gAXGnOhj/m8OpucYOU37jR2pkWF08JC0OmCbxwI\n7ZSmWDKcwuG5wPTUYPTIHtOA3vyUJPXlcp/pYDVP6iOYp21JrmO6RKJ5Mf9B\nqWeJKVmxtSfM76BTVQMkPtl1Wsrm+canvJosw8ZWyYPa4oJlsucJyjLGHk/c\nc11Bfsnk+PComB4RXcG4qQ79X8xmRVrcVEMo01nEvIsGQdO50Ku+XuYzeA4R\n8KgRyVJHuQmChe3Ggrge2pXP3KQ39vWYF2k1TRAYag1L88eYFgObpVMEzXcU\n3/Lb4qLIakqNGCMF6PL3eU/70eTzz9/+/RPxneUC5fCno3k5VfCHQabMhwTy\ncFDuSYKPIQgSsBOys0IgPgF9i1PyuBbFVLnvVP5wHcTnbfA+TIPzT1uEKuvA\nkOP5a94PmugYA9yeIdpmkRJb8Fo/r39E8FxBolcovI1Q8rtxnX26giuSLEff\n4ePixoVaktbb+6/QBVWXB3lapJ4mX8jSXj7xW9AZYaKv6z0lT3rXXq1p4DMa\nNso79z25gaMIzO5lLxvmRk7L+0clWu5d12l/VYVDfgEID4w5Id6O9ZdcgyV/\n7GExoppSAaonXVU8fXBfzVDALBAeUOiNfNJOwwAGKmoMY5K669BGti0LhOvA\n41P+\r\n=CtOU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDCHHQRTEB80yvcGz14N8Al34p+7Ol63yfLJg53AFUdIAiEA3deKsi+0CyX1cFodnhFSJqiHy2CeKvwox8LFVqQwARg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.28-alpha.0-testplanid_1539828828908_0.5978816237026294"},"_hasShrinkwrap":false},"0.12.28-alpha.1-testplanid":{"name":"teambition-sdk","version":"0.12.28-alpha.1-testplanid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.28-alpha.1-testplanid","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-HkkW3KOsCEutiOR82A0KOuj4mjx4Ru33bud7/T8mARzSwhsHtI4l7rdmre+49H55aGqYZYOdZ1/bziM27NwHcg==","shasum":"577c1ca3a0faae75b9c47e8a77a7bf4c2f648e63","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.28-alpha.1-testplanid.tgz","fileCount":395,"unpackedSize":823492,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbx+9dCRA9TVsSAnZWagAAke8P/RmE8ef91SYkD5Aa5N01\nURBFaEJQdV1fA0XyYM1eQ1eWAM0UNidRTbUNKaM3xsQ/pZE5PHPK+9rJvdMd\n2TsKfmA/JAwRgDmBP0lyPVMPuZYp1/rMVfuR7hqFsveHmWR8EvskGV+pEc2i\nSzOFNdwRMbgHuo4bBi7maodczwrX2d+j5j5m5Ph0++fDgulsqqAe4IKtnAxT\nqKm8BuxR68nn8GMBW7LIGohMgXDucsEYkoRW/2hihRyBNhQyNhd+XlrkG0K/\nrSeE0Q+JbGCjwMk/DOyYM0JD2xN9aKpfM+UjwKKg/glvILN6oU4JSMxdeER8\n7+Kgbd8Yl9AQq8VhrPBSaotdkQJ2IMuCyJBaUcNJ06UJX0e3bfmWD7tLTQg1\nOezEZDCjdZ4adWTWj7jGFB+r3MRKFkhmIZQwh6MkeL2UylBjJAqCQ/NchHR/\nDm0X5nR5IQE513yp7eUeLSiqhHmHt3AecHVBL9k1leHes+zI7xe7uCo/Qpq/\nQMeRSiMR75Ml//PelDX5fONsqwWbbudgyylzDt4/20H7GMUe4NpoUBFbCj7B\n5Qhg1uevHYdrpeSJo4JbgIlQixCnS+rWqk+At1LaKPQ8w+URcEhifowklsqd\nvXfhLfx4vWyBcK5XNmp+TPmmsIJlB7KzHnq/X4TZLadJtWGkadPywgcRg84M\nveII\r\n=6D3w\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCgkBtOLCrJzXAEvbg8XLTmcBytHg9zt+ys4NF3q40O3wIhAIJ+ffzTWriJjrvw8OvVI0SMZSyq1Ukf9hqDIn7nV7P/"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.28-alpha.1-testplanid_1539829597128_0.14898618015027854"},"_hasShrinkwrap":false},"0.12.28":{"name":"teambition-sdk","version":"0.12.28","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.28","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-fh2UjKAKbE0cSYssxG5vkqL+eywRG6XVjHkoQ6qgLFvVeXlETjywnmUjH7fkAfNlBzuQVTUB+TqHhBqAmHCbkw==","shasum":"bdc6501e5eeb7117703a9b4c6e9d46fa506bda8b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.28.tgz","fileCount":395,"unpackedSize":823703,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbx/EyCRA9TVsSAnZWagAA7AAP/0p0C/4eQgc/F4Qy25l0\nmT+HuvkuAlSzsRFU/Sp1+qKqy6KfGEUR9LYatRR+8Z4GDqobw/rH0NHHeyhD\nUzQRIa+PnY2+SSuCPA1U14orWv5ft2iaQ3bEe0myEk1AFTDT42BIqLTqJH4I\nZRbS8mDSRqu9yOsKiDznhjENWKnwVQmbPH8VPNhjBqyhQWk4B1a9xIokw185\nROjzZuOYvGxfzuykAkeuurmYX6yznlMVChOL+omVaF5JibS4Jx5VuA4ysWKl\nUZK11E97BnUWg2Sz/T6YHb1RIuOVRouj9ITfuVjuIAoazOt6B9m5eJ3lSbda\n+/yItfk0yF/yARugRNcx+83GeyoIM80TrQPqkURWWl31Ox8CgzBqPg9hxYgj\ntQSEfgd5OR2rtRb+m26a2hTvI5tf5ruNDL3G4tDNQSziTYVuZ2NrdoPDtBh4\n9jbstB9RgyKpTrG0kkk+Y7Ao1MABJUbqys6vA/IhWrNCsqsZ5WW8suRfUQ90\noOKVxGWvP1HX+kilDgIcZO6v3S7uS1YstLYCS63YuzvGO7VhdWwtXBIOzc3E\n/EBRtMc+m/LsRrz7WYuAtUU2kpsSlcGk3rxeeKFpOXHDOa+493UnyJbbj4nj\nsJ6RthROAgLHxkzYJWzLqJWxK/Cj2PSxw7utXrXj4RXOF5bn9W2PefugigPL\nZYOw\r\n=IAkJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCI94XNLAz8KzFSDKw+LC+ZtGxPs4Ywt1zq4gGBYnCQLQIhALnnbFHDm/duvxEXIHP5wF2lF9qkSQmbRJp1rE/OBCrx"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.28_1539830065614_0.861339043176323"},"_hasShrinkwrap":false},"0.6.28":{"name":"teambition-sdk","version":"0.6.28","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish --tag legacy && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ --tag legacy && npm publish .tmp/socket/ --tag legacy"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"5","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^9.6.6","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","atob":"^2.1.1","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"5","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^6.0.0","tslib":"^1.9.0","tslint":"^5.9.1","typescript":"^2.8.3","whatwg-fetch":"^2.0.0"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/master.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/master)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=master)](https://coveralls.io/github/teambition/teambition-sdk?branch=master)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport { TasksAPI } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.TaskAPI.get(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  constructor(\n    private TasksAPI: TasksAPI\n  ) { }\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport { PermissionAPI, TasksAPI, ProjectAPI } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.TaskAPI.get(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => this.ProjectAPI.get(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return this.PermissionAPI.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  constructor(\n    private TasksAPI: TasksAPI,\n    private PermissionAPI: PermissionAPI\n  ) { }\n}\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n","readmeFilename":"README.md","gitHead":"2d774ba1ef3d35f85b82318b8dd37bdf1c018ff0","_id":"teambition-sdk@0.6.28","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-1wGZjtyIMiz4duYGHWtP7tCV5YHR0DO1QNOd77Zazd/s8p+gh2T3MYgdZ954w758+pM9h3hWvSAy/rXteH5neg==","shasum":"52d4d52acd9bb1db9aa1efd7cc22a38bc654f69a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.28.tgz","fileCount":1217,"unpackedSize":4565640,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbyYZvCRA9TVsSAnZWagAAkQ8P/0cQLZFGUg6qHGmZVbqp\nE/z4ulmUrTRkWxKz74TKgTudsBVHWyD8KJvC+d2u5GTeRwjkMMvVo0hCGXDt\nqqLv5xsMejhKds7c1iuLO6ZIDFaSz5G3/eYbKhLdyU3ZjxhdzlaQIQTWpXDW\nD6wlJVdkmShv4bLPqhzPwwak4vwHu3f3xJ8VExiaRRhMxiqbi7XyBHqhgX43\nU8Z38IOyICfHDVqLSFN7IXKS2CZmpjGSEdXJzHLnoLJQdD1eBkpMBj2FXOF/\nlqHkC0NbpkydqqoBC1GojLSpyGE1aXLy6jufMfEOYpEuTcBi3FDZv+p1ULcp\ni7zaKAkYfxixrPs/iIt/nH4Ca8fPR3yRQ0bN5RFyqx97NEQHC6aAdaB/6Yoy\nXIfqFrg/DXGXnZ8hL1KnVo6bmIvX1qqe9SjlL58EGhAUx1c+Z7WAkc4c0ui5\nYgKOkQEvO5NEdg9w4d9UxtNaZnocXwAEPH2saOzhArZLCNYV4QurkZUNNhYp\nmVKDFz2ensLiPWPg3vC7BS++qMzRtoSqLxSzqlbqbGS78WEi7Uo+vl0gYqTd\n/dyfkh/5fKRQ6yU3xunNHCA+VHYUdPvJHN/ENRyySLbyMd3eBfil0j15IaRE\nW5suNLvVzfglRpnpwNSbGBhbXCgkipqN42oH6cEVjaefhx/ulZ+Veksv65+O\nOHS1\r\n=kRR/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCmaJP1qqj3KnJ5VCKtPEuC8/otrd7Hrj/YgUdv3E5ZfAIgfKWuX3SZrzUAddqii8C2hfKHY4ZksIUgxaC73eGuUmg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.28_1539933806785_0.8196714716045306"},"_hasShrinkwrap":false},"0.12.29":{"name":"teambition-sdk","version":"0.12.29","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.2.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.29","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-IvKbAYO9D2uicr/WnoIntLNL7aS6hMtR9sRneM0zrMCWPD1VDmu2uiDplpPzi67OVBmZpNeLYS7n6g9S+RA+jQ==","shasum":"7beea6af77a9537923e7c6da95efcc9c8397c62e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.29.tgz","fileCount":395,"unpackedSize":823703,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0Q+MCRA9TVsSAnZWagAArUQP/2qyioFXg16vJThIm27Q\ndGBRVF9iCmYjgXJMDLoxheiZEvqS7zdrH0dWDHuNxtYnMbQW94slFuOCVDFf\na4yWbtQMu5+vwAhfm39fDfXJbVJiFMx3iC0btKiDrNJ2KionDV7fswHyfBeF\neBnoT1i8WFzQcLLfQKObz+5TjwSGjSP6JbKknSnVSkxFS7yKnr5EJJAliRTb\nHR0cSEAhZ50DNf3Oyc/OKPq1IQlSaFjsyeq7HVLTrGHe6kQndNWapVROy1HC\nTr+CGGSXShNGsfXlFkxLWNZUcaH8wKIViFv0rEG0zhbFzgiudM654lpK83Sc\nJt06YActp2zy9XuHG3YeqfKKuubb7z//lSuLXUkO2pTUgT2E2qPs8+6zusyc\noC4tu8LXPhVZCmbFRrf4omTJsA/UzKRpGu/Q+oD+qfAIkifAjXIM8KinK8QT\n83X+4lct7ycXJoEbG0BbC8QtpwydJNCxoVbD+qNVkHYLVSe8J7ARJIQ8moW9\nyjnx6wWZzDaUe+eWuQoYYAG52Ft2VVWrfjAaZssi9Of96jeKIytdbFZYlmrN\ng0etSz7wuwmKpLclUOV7h3z/tdu+Q0cOzmyKeeWyO28cgMgAwLMjpOkNOD55\nUF+LJ+C2dZi/SK1YJuZ90+EGzxSvmE9Q1Duugy6lSXmB1/UrOgyIP0imGKAc\nSUZp\r\n=Nk+S\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCyQIa4x7nrjWJhCsO6Ablci+L8vNs5uw9VtsHtsa7q6AIhANzaePVdCWzeiyfNV7OF2mvXaojcx6ms3hdfux9pr5f0"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.29_1540427659883_0.8520247882182106"},"_hasShrinkwrap":false},"0.12.30":{"name":"teambition-sdk","version":"0.12.30","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.30","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-3Db+SXhcfXkARQztCf7iYsplims5+4YxXfj76Fn3mP4JhwMTyvvixsUmFJFIDWn3hwJB1/c60bN+FreC8lI0Zw==","shasum":"5d45d579a650d2fc33dc06d136587a7672975f61","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.30.tgz","fileCount":395,"unpackedSize":823703,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0cgFCRA9TVsSAnZWagAAXicP/3AUj3tW2ZTVazwAli1f\nY8F3xSVliNlO+Emo4z32cRUj7YJ83n/WRINdMC9DcKqBucjjGcQF+Wjn3SoC\n+jXDvt7WRcLX4wi6Fcyp8ggxizMxeW9mb/yA/eEYZ+YEWqjLFzE1HBnv/nXt\nYAC/fceiqE0z1gjt4mpjb37qSLeDB273K5+eaeqJ++/jK7F9FfJIxKlfADvP\neRaEIAYVFgBo2fHh/V/I4aY8od8jEbdrL/quPmfKAJCh22m/fSYsP18FMOBU\nHuzJev4wCDzvaudDUEvxlfHt9RLSOBS5KbxfWmakoVmdCxD8egvd/8Bzhu7R\n9T3sfQVnZnuNOGre9KPmikhUIPuQ7Y7AGhb6sH9B8sfJ7ullPtTHsFI3yN1C\n7+/oohvLuhr/YreOOZbcECDNmKtznhGfHC8F+q+K1PmdgQs2blYD8fox19Yg\nSgp5Weon2aLSmAQ3HGDxjrzE27Nk4xvJjpQkmQ3Xl3Yft4mQczyl8MI3K5Wu\nw9Xgv0t8lVT8h4iV03QUe3+1V2+AnoI1FBtyjHUnTjT8ityQN9o5CpYsAicr\nadNKgJSLUq/D4fZ+S7IQuERbU/HO423h4ABXQI0b5mL2eEfYg61zwnxwwACn\nwbF1JtOdRT6aD2MZoCxCUZ7W1jPG9Ynl0sEFT8gmalnVAslMS+NAMbeixB+L\n9yM8\r\n=HuhF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDG6n6CPTA7jmhi1YZr5ItwwLnQOFSEnpNwMf/P2acpjQIgBeqU3aAP28vsTmNcv0Y1Q8e7pGEVZPGfsY2aOhL9B0g="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.30_1540474884560_0.34350745987825193"},"_hasShrinkwrap":false},"0.12.31-alpha.0-projportal":{"name":"teambition-sdk","version":"0.12.31-alpha.0-projportal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.31-alpha.0-projportal","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-QIBqTIVbA/1vYk/ah2yO3FDqbzK2jUjwpBNcp1DBt4uTsknbQTEGtcivtOa27OQXg3UI06FXz0gP8cdH3OQBdA==","shasum":"4a1908d988e3f2e9d8647e807b235aeac98e088d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.31-alpha.0-projportal.tgz","fileCount":395,"unpackedSize":824703,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0ckuCRA9TVsSAnZWagAA4C4P/21scpxBMuOx03Obfsk4\nFh60QiTN/3XJzis02xBIQFynVX1Fyd1yxhrpBmu0GXZLJ2MnfJEgBDNwiyUO\nMkOh/3O9Pw36kjbx4BkW7b3+GsxQzKm8zrrjoLKhPR0qb2S4ZVjTXVRsc3LL\nnmOskh/loH0ucEp6fvhTiMl9lPMYBRZindAS1fkulZ0cJncabLpYQMqH2HTM\nhpCP3pjQM7PcNo4iqFAfc2MXrUKoC6caT2MgUdNCcXmsEhYlWfWf2MSSjpoP\nvQcyzpHVMcaCGwsE4HC4TMHO5EZkYAQEsERetnRB0v4WKI9p+fCsmuRt57Vi\nSy/6DRkkH2LwkKCow4JYmjVdSSwpgKi2YmsJnvF5jV1QXIMNiC8KgtaB/l0+\nYbVEGY1Prt5Ch+xt43ub5CLEwY/ppiUpRfRQ5I48vadgUvEq3m+0cLPGJ6SF\nA7YFkxFHwjVFGmqe1QyRjvSpQphpJd8GS/KgZKA/Zq5MadZ0FYGczVR4xFUo\n5Se6AiIAFKiK6rz/iY986BH7tLUS+rF4L7NNIWG83eVmNn4WNRvDl8lp/pWA\nV71ImoZFTI7AyqhV6H4EGi9riEeTd5yIMyg6j9eCCaGdByObmagYvYS7LfMw\n2fDpfD9AmxBY1sAr14oLEqLJruHzaX4trzYsH76pQOg4HBl/FPHgsyndOhCu\nangd\r\n=lgGa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD7Qn1ysBbhm5EQqzTxfHXzM+++e8r806z0wD7txu7DqQIge83AENzwsEVlVRHDoXtE4egyaVDnZRRXvUMjBK4Rf6A="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.31-alpha.0-projportal_1540475181912_0.9829452514720014"},"_hasShrinkwrap":false},"0.12.31":{"name":"teambition-sdk","version":"0.12.31","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.31","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-OihQey3GanZoro4+Q4cedr76pMABZ1Gos61Ab8LcVxU9iineXEo5/lupcvouFNERYAglUDXVTDOpe32stD4nYw==","shasum":"721b3f1d65736b6a0b83b94611cd9c4fad22ee9c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.31.tgz","fileCount":395,"unpackedSize":823771,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0nvUCRA9TVsSAnZWagAAHR4P/jjkQyk6cAEF7XOEtVjj\nHsgwp82rR+x2T5BF7IHEc5NrAqUTHm1gDCSoe9Oy0ABUA4pvYd3O3IBHh6yH\n5lNPJcpeoxnuUHGdSdFNo8iURVfG7++xLzlPLEVKS0GzhM2BPyW7V+5ygJBp\nyGPV2lxiQssLCpxaL0VGfPZfPYXQuZ2AMqz5rknwcyQyNaDbRPo6eXdJcigo\nqZE2x3fFuIxGHxq2aeSxz4NlK2jf9VIsus3Flk9bVsg02yWr9zrzoHN7NuUn\nwgI7gC+JTKBcngUaq5hs7nxznE5zZHvRN1FRUKtmpHIQQSpKc82R1H4DyQ1f\nS8AZszWgL/yKdEPmuUuWIuV6ftph+NVXAx5hFGozzVVXCHTrP34jAwDG7G4c\nz87gqdZZSK5dDIHAyH1ACrmGxRYBaKZVAMhdSAXGDfUvD/dp9cLnq+XtXYAY\n0q7cmKAtoov4HPMeKhO5h1mTpQfXHR2qdrLr+zJewk3DJRwVaKrGXAct/Q1M\nZ/ihpnB338pC2kaMQlqxmYRbSHml611YgMpC7bn/GapXgByMFaZfN5LtJAN0\n+bxMWpny0bQYmikhtp+a2iBrkfrRBHdZegeQJcU27CVgzjV+kC7RNidhWN8m\nQx793UavZyAvK6VCpFJ+fMHg3cv1m/69/vK4s2DnGALIl2Wjw0f+0bCmcUiK\nuBxk\r\n=8Bmu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDFJzvi4KAhAAr306rB2pn7XOZUInjpPziSaBN6XR7yUAIhAOcjSCEHhvSW3yvn05Z2w2FSmW4sIl3wMRXUy76o96eZ"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.31_1540520915885_0.1312911596061317"},"_hasShrinkwrap":false},"0.12.32":{"name":"teambition-sdk","version":"0.12.32","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.32","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-vdXRWqC4xMScWNzWDKM/PBebqmFGmXO7Lpi2H1uwek2szyKVGFe8rsFINGs534o46O645pefMGWDSM15456oIQ==","shasum":"ac197d09aad97fb8d6461e6163cade10af7d5882","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.32.tgz","fileCount":395,"unpackedSize":823791,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0rrUCRA9TVsSAnZWagAAMpoP/0vP5fnMNTio1Mly4yCg\ndLaHPx2o2XnL8zw1QRc2zPBb5AIYNfZg0M0/SLKKY02yeJMfmB/FdQ6ug6tL\nqSw0Lg9NubdjRkluqkdMcXKUKnNvNNDYOo7AEdJJLZiHa0U5QQIX/abPY6pw\nfA4HrQFihkenvEXiPBY1DSm/tH5GMiG452Z87436r9FfvziSFZ3CWW1KMZIN\nwaHUbCNeTsLgCTXuiYe2Eo1qcsopB3biDcXwGA1Q/9vK7MEiXKGVz3F59os7\nCkxl505YCCpbRulqTM984nQ/YrLmNTWv/ZAGOVN3amgqHt8gxOlAKHZbAQzw\neJ6JjG2jW3vQ0JYIhg7bEStyQ6VAr4uZSKNglQXaTUs1vt90tZkynT/tgKt3\nUBeOeSUgYdtR0SYxjVnctIsQQ30Xux3r997LaYeapunR+/a1L2m22rzQ/Q4w\nEqCLLCxkzmcfMYpsDnn+dTpif5jmpbQ58cmZnbUAyGF8flEtjcP03sQBa5V3\nQcE0Tbf4ss1XtR0SYSCRUO8x/UW13uuMky8R4acC1pJ2DymcWmDh7r4YBoSH\nNerSlZYn47KNeenwUO5pU0j/d0zepTtkjjxIZreOJ3ZCXpnTQYMKpzfbq6uj\nChmdDS3eN7mNDwpB7BlDTMHmQ4VCzoSuJhYi4WmMII28mtzBt9KLnNsr96mL\nP/EQ\r\n=c+sD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE3X+aAwgtZ+CFRBuul868zzErSmFzTOpO7plQVtK1jDAiEAvFFpOAbleRe5NG+xwt5wMQcsQzblVBsYLhhlpMOeeVo="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.32_1540537044123_0.5176210725397343"},"_hasShrinkwrap":false},"0.12.33-alpha.0-projschema":{"name":"teambition-sdk","version":"0.12.33-alpha.0-projschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.33-alpha.0-projschema","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-LQkNxILkc4oCbyQq6U8G21JeXHHCnamMzTSAfIsuk8Rx1yw2+UA9YbH78w5TM6wbE+/xU7pg3OVVJJ+Ohuhy+Q==","shasum":"c112c4e33e979b23d9afe9759680cafe90bb0d44","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.33-alpha.0-projschema.tgz","fileCount":395,"unpackedSize":825060,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0tF9CRA9TVsSAnZWagAATeUP+wZKXt9t/Ai7r83W8fzm\npGpKISFf8STtMr71GzCuUTtvrlW2Y5ZivtUjSblH8lgtUsd5fpCuY1KKPsii\nm7dQuI8sMSfqTR36j1ewIPLhVWy0R+CMkAAEAcdMQRUpNy+Z9oVYhisr+FJe\n8jzQ2XuFVMteyo5aV8vUkogkmCeqwfF89AyZ0W+B7FNoSlHVGXFKiiywphTc\nX4V8dlCWdXKS74KGtuS2/odEowSd7+t/V4tiy7tAbVthoRooYNU5ljiBNYdZ\nLQEzDCJRRlHAZoBXYxUH050+r015bVwfR6NZEUUSPWm2J/F7hWt6rSJk0GgM\nYqUU9xhVBTJO4HDQHQ0/nvQYQHoZ1WC1OSh3bbC1ZHetFtfeIFvU5iGswbB3\n6kIUJ2FvqohLaQdhw/TVcPJ8rJz6G9rchwyri+hy04n0c55V9uzVqYC4boZe\n0RBk5DU4NnHj4NMkHvrbMh/b93CNZjE3lZ78iLEtgUozcOK4gU+JW/Z/cFR3\ndC4YNu4DSiZYGB4bnHIvHliO4pbsW+T/J7LTAaVPU+/9gfgtjY2z+6M4M/Pt\nFWWcTXR087D/ur9IpKHS3H5uVqBRRPbtseQrLWR/i6jkjcDcCK13d4smT4xt\nZFse4fdWVloxJ6rJgNhYJUXIvVeXpTrGXC5tJ5dy6x0bZR/Rbqenb33fhgg3\nSyeO\r\n=KVPR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH+nmykmssjeyFTk9GsSGXTTO6udHT/WBQqjEvirJZN+AiEA1h47Pfr1kwcnA6Re5nKElGVRG+BL3bel8QvhwjCAc8k="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.33-alpha.0-projschema_1540542844669_0.8812138737072124"},"_hasShrinkwrap":false},"0.12.33-alpha.1-polypage":{"name":"teambition-sdk","version":"0.12.33-alpha.1-polypage","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.2.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.33-alpha.1-polypage","_npmVersion":"5.8.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-M2Uu2nPhU7ZQGv6LIFdfrrpkBHZTGSycAZBxIuP1/c5NvSHNfho+H6aeBhpOxQjgfUYh2/EGWRR4uxOP+7unJw==","shasum":"99751cb7defb517a7605ab6c9ddc11b5c88771fd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.33-alpha.1-polypage.tgz","fileCount":395,"unpackedSize":834735,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb17qMCRA9TVsSAnZWagAAIf0QAJvNFeAa5CtPfPZEbXTh\n7xdI/xGjyR/pxe6InsjKD54w66B3xCATP0DES7vfZemLymX0j0yI3nFAgkat\nTpYviJlDf+jDbAnbMwWUAoHfpmjhjlWOiSa3OLQME/EJWQLkeeg78jF+ZCAr\nVl91Ak+/nFdRZ66wMuF8oftc06GTJfvz/5BVV2F2pl1ClzTQAtZxmWJBioJE\nQF0MDILSB+ZB/kS+jKO8zblip/qTcrvS+lbS3AC4LgAtr0s6nJrPUGBtnioD\nDB4ldLFCAv8dIsI67TC3i8tkst4fvylh2NBOxbiwca7ayQbU5c+vyj+4Dw5s\nT9MZ8UxB6jYFvZzvsR5n1XJ0IeDr/oM9OxiulEUs+Lf27eB4J2LYFbgrYF8P\nFgrerpktAnsuvTYvhuA3j55+KDTJt071ABAT/1QQ9d5Fm546llpu++4/hmWf\npWF9pDBIy5oapsbf0wOOz/FnjMp2q9NKQ3vCYvI1DTaXSk1GTmY6VsfoEdzN\n2OYOpf4HENMegMOECR/dxAfz0eedd1CLxcmGr45wHwDDcFs8pn6bgA1u1lOJ\nR3/FSXAN+BrkeLDpKue7CKCv4PFdkubsGc1nKV5mIXNStRlIZbGctFVZhBae\nGT2t01+xCIi42/R5gvRLmgRWMdQJ/FeBc18Ds5qL/ItIrenjPwIT8X8ocV2R\nTPiW\r\n=/CfQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD3+D5CyT7dpS5w7IFeCh5jGr0RIF6xpXshIvMjhhudAQIgMuk8M72MKyeWSzojRFZ/g9E8EXB4gC35ftqaZlfCdPo="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.33-alpha.1-polypage_1540864651779_0.5891809751867738"},"_hasShrinkwrap":false},"0.12.33-alpha.2-polypage":{"name":"teambition-sdk","version":"0.12.33-alpha.2-polypage","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.2.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.33-alpha.2-polypage","_npmVersion":"5.8.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-Swok11bN9CS4++0moMXwcAopkenA+NtyqSeEwieUYO35c7yx02KR2Fnp0+qljzO2wXfCf5IewzNswWwIWzXq5A==","shasum":"108f0e790e993df2644815c8ca6e73230d14fd04","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.33-alpha.2-polypage.tgz","fileCount":395,"unpackedSize":835077,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2CboCRA9TVsSAnZWagAA1cEP/2JOf6ty1LNWyoojyHjc\nJqPQcq6ZIjlutoCsh27uhs9k9p/HEDPnMPJ0eNNwpwzY4RfT/mas9LwIe79+\nv0UeBEJanGEaB2S4tBYpVcyfP0N6x/oqExufEo1AwPbfvffR/cCmEXzyr9wL\njtQmeezTC7bJSmn9KLvzukq44xKuof/2cdQkjC4mvAcmA6BLhopvZ4Dh4DTw\nDc+NZwV/M0W1IRRni48X8NeculQ2Ie/8EJbfE1dkwPWemSln/KkoYE2Dz3vk\neZPrfkvKki1EWGIeDanWNbAB5nYCn7citoajF0SfgUBRIDpZgqwICvB2q+14\nRzHoCJ1vDpctQ4A0T+wmCRAXm/2hMb4SZgw47zrWm6uIB7soSF5Noe/D/KFC\nfuazTpxh9pdM/3i3+Wji4/wiy5MlKy+ZTWCN37yijL/5kIxR/tvikA2x3sLb\ncvKHm2iwbzhX18ogXERUR8U4IWsgJvDmf4yGAG/uINT3n9Vk+18DhuA9oXbV\ni0P2r6Po73lDbNKsWuC6O8jqvBvh7vDmYKhCoic4e4q/zLCG1ylQoUT61/Nw\nk/mCo7XqzaWJOw7hqZhmNajdV25pOEAsUVYOF9fS2w744zj7Qb0pwLFWoDdQ\niResqEQTCReBki6WO5oeNf2frwamUGpmfg+KpH8BjAYpNvWIuhDVFj2ftC8k\n1k1w\r\n=iYo5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDePZex2T2r+cTVneE14cM5CjA4YrIQGDW9Isl60qMf0AIhALbYNN3amLgNf/yTOaQzLLvdF3nn07UXoBjsgJidthDK"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.33-alpha.2-polypage_1540892392077_0.2800087502510826"},"_hasShrinkwrap":false},"0.12.33-alpha.3-ts3":{"name":"teambition-sdk","version":"0.12.33-alpha.3-ts3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.2.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.4","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.33-alpha.3-ts3","_npmVersion":"5.8.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-x8lFtuiAeFIaw0c2GgSJFt/CWvVKZ6kYxh6x2qdxY15cEwu63RhQYuC+m5OJZFR8BCiYWPcZetRcOcYK7XYU7g==","shasum":"22cb629d0b01f77cc37c452b19f4acc167484722","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.33-alpha.3-ts3.tgz","fileCount":395,"unpackedSize":823803,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2DmDCRA9TVsSAnZWagAArsYP/ioSEDYS73uwnVBEb8+D\nP45K3yYEvyZiS7Pq/UWiQ0Y0yWS82ksVZL+l4/eoMeDsY+li1QWdUI+krWgz\nmcnATx7m0zDRkkwNMfhd9m/wVGdslMoCandtQJKpVIcsqZIa/IgZ1NotFgB/\nZPFnXxyKWFtYtQfTS86GOAtUUvCZtvWA2PMqsAot0DRZBTqvapH73hF7DQyP\nQIUUE1myuCB305cKSzElMsZH0taNbXhYG81exXvIRVYgUseY8RQW9eEEPJoO\n5M4fBhZU0bcbnV5XHFk8TtkNgzX3cWq9CgzY625TIoAXXUsVRmndbgR/tdb9\nZ7QskivYcI1is8jNMAFPpnf6O8+6+pg8XqvWnekgnaXo/8uxgYBRPwE/N2cd\nd6SEUyVWISp33RekuaEzfyfQz6apAhR/63+pcVxO7B67M08KvKp4ETnQljFw\n8w2KGPt+PY0uhq/6sHfCiX9C3MJfAgEFVT8+39QNimDE70d8hziHfnAV4gjv\nmL4igNidIcCnz6PxTmh/oR15/RpKbm6sz+k48dCrbXBdLrgx0V3yFQhnQsbT\nA1CcBuV3WKaT4shp6RgOxd2htaskoXsgA57VRtpskCQOfSOf4ASx+h4BG1Pr\nqRSev6HyLwVxzhx3roFoqiUNFedXg4Onee+vy34vAN+KIk1jt2h5dwywcJEw\nvCAc\r\n=uv9F\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEcFQ9SZq5tz4JUt16hODxVI2bka2AdSd33OL7NKkKsoAiEA7hpoaaj9FZELI9xgxFW+EFrOqBa7PS/PIcq+/qkxHWY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.33-alpha.3-ts3_1540897154492_0.3700868998619089"},"_hasShrinkwrap":false},"0.12.33":{"name":"teambition-sdk","version":"0.12.33","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.33","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-hgAZjRUfTa7AEi3bdnFh+wi7D1j9d5sCsFozos3O/HBDAcjLO92WmV1yuVcLtr5orKF0W8KEmJXJBVmqQ5u4ZQ==","shasum":"a671a1af25210a762f5dabb82039e179fab3a254","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.33.tgz","fileCount":395,"unpackedSize":823982,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2IXUCRA9TVsSAnZWagAAC1YP/1dgMMslpTnn1WoWdL1Q\n4tyDBnTV+LEU0JVXjNnw19SmnMy3Ta1x8embYR48txncXylwZOla0KQO0Wk0\nvL2TKbBBk9AkM964mXZF8ySXBtg2QsHogclTGNkwGtCXiXJxRauW4UqPGV+r\nzO6n4lS89gR3M4+AdaKKONspwy3iOEDLYM/btcsZgeB7sweFIJouOpdQoMbB\n0mMwJNbYZmXxsHY933poScCiE0qFAP51Nbv3nPPriEOiHpYAbSFRal9tAbg+\ntNmgUKveuOpmyMcNwYhU2J3ufkg/xyFPhB/uD79CZveEDDSa5Y9w+xlM3hUy\n4tjjop+xRhoP4GdTMSRARlLPsA2ZHIgyPujEDOX96ze7mFRfU+GDAcRg/i2o\n6XI/A4EVsH7s+icqAMEnZBKjmDUfcbIe3A+d75cSTYUeIJkcJJy1I+hwzA3R\niznliyvoPB2n3UYdcNqmeIWGWB0v++qsRqCRt7su5kZ/Ta3wONdA1F6v7w3e\noWy1ejvTLB0jw/C9YtqbKMHfdMlgThR338pRBe2UIYcs5x3T0iwaz8b0FUvu\nUBsr7qA0jg9jKgANbXB6ak7cVZdSNrBDOxcKOW2x90groGm39vPLXztzMj2m\n70StX9/I56TwZTIqKYzGHJuith4v8Ud9cmJb1EzSiI4AqP8OrNRbqCkalBkz\nMTYs\r\n=h1Bw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFj6FJjzSDeNabzT0FLQlsoOd4rBCizKCNVo4syHoMm6AiBxSsXUPkrzuQrwUoopnLdN0/jaEqqhiCIFNtC2tiLDAA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.33_1540916691842_0.9915129151246516"},"_hasShrinkwrap":false},"0.12.34-alpha.0-perm":{"name":"teambition-sdk","version":"0.12.34-alpha.0-perm","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.34-alpha.0-perm","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-nJ9qjExKGSiznzhZEOsEbToRbp7P8hWis6hX+7PdLWblbuig+VWmIa/Be5cJawTATEc7HrPQwYkY4h/LrGPgvA==","shasum":"dc6ffccb37b2cf51cbdd6c8e3114739a8487dc12","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.34-alpha.0-perm.tgz","fileCount":395,"unpackedSize":826226,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2I2KCRA9TVsSAnZWagAAZfcP+wdlUuxD985qf1knuk1V\nomVtbb/CVnZcVb/9MlhgtnBtRW8xRDyOPdYEvEW7qDN7fc0tOE8DvfTuvN5B\ntchNNGifgk2D+/4gMTMQfRlakdPmgoXciYldhj+x20hgXp7YIB5slKtDBagb\nTaqfnFTw8s4o5Z1SdoicpckJ0WA6qZr8ASXyq5LWbnYu9mzl97t7GPtq2PO7\nqr8lFVsH0D3Jqw0Ue3meSjm0+DiCO/OEYMhfifDVYxKQYD7tH9G+y2Y2acVw\nYUYLOLsUH0PSiD2x01Msfs65+u9khtT9Ug5mTyrBciWh8iJC7PiAhUxGCOW/\ndFyFEL36FLEojLWqHgm4TJp39fkh7CIGhSPOu+2hmb6Aup972soWoyG9oCCP\nMfVwg8RwoEC13yfWdDZCJC03fqOhIMMknfQKSsUAxEoI9ePTgfAxRs5V9kBO\nc/snSGHqIoc0PzLR9nZjNAXssBNb19c+KVwkCbnSaAfSrB22c7Orxhk886W6\n0CSGYYp8alpcpesX6gajsZzLynklEzuVXdg/7CfZlK/NOIAdDxkDIJicJ/1w\nSE8iP51DnM4eMoQWp5XpoyHV0kuiNFYHF30KdOQjTnxQC/NKs+qZGZfs33xP\nBSjTVuI2eff0mlDA78+YJZDkgaxMMaFAdK0aYVCM7/AA6KSkAMBAy+dADa5z\nQpom\r\n=SDUL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDeMvrFg3njvmKqG5QIa6fd4P7Zt3UIJnqT0ODf8olXqwIgDBxOQBBcm4BRikrgHnkEhTY8G3bJmkeZwwCDJUHrvfw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.34-alpha.0-perm_1540918666110_0.548125229562245"},"_hasShrinkwrap":false},"0.12.34-alpha.1-rollbackpadding":{"name":"teambition-sdk","version":"0.12.34-alpha.1-rollbackpadding","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.34-alpha.1-rollbackpadding","_npmVersion":"5.8.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-74950xM62dy5euPTzrlCK+MHEu2r/m5x/b7Xxz5b6UxK7xUyr5SJvRCu174uFFkrpsO5LVkrEtBHifjQFAtNvQ==","shasum":"891d9a40ab2d38ac9931f28be73b21bc44dbed1a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.34-alpha.1-rollbackpadding.tgz","fileCount":395,"unpackedSize":824566,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2S5gCRA9TVsSAnZWagAAmbgQAJqGzQIuhYVUcdxFuRd7\nS+dpjZamb1duCxkicW4z1+L8sKu5R0Of72tA93rEtZx6l+Zp6ijSFXbnqBah\nxaNF4p4UdMxjFd7I+Bibno6z8AnHHBlKu2Z2gT8+mWWbadbHr/pt7BPz2mCm\nkpcAOw8iNTXsWeCJCXAfzmhJ+tDuCSpx489Z8xqxjkhC70sCISwrbu0/bF/v\nyU4eOfTtAWeaLRA0ozdnX1euLIcrveLQ917Mg5ePFtLNcv5N3xeuQkHVeKGE\n4m/R1t1DXpUFa3B3QvuHy0VO0ZS6B2iFlp0N920CdL2weU9Bw92RHigniJn8\n5cC2Vb5/eDFjD/4OaYzU7cZUuiPmU65IPBnYDlXdVHQV9uWVBJOWBEhk/Re6\naHuOGgLMql8zuc2W1C30+7BHjFjwxjtn3agp1amqJpTRMeyM8sP694Eq4S0J\nzVcBW0GnAmvbJjjgNqNUZ5LeXnE2CQtJpZK9QVTc6h8Pg5SOdw0IW5S5dsha\nizHOKNlq2D7c7BAYMWekoOotylXDAEgZ0PJ/XIyh5tayZvMNVFyep0TGfl7b\nHZUVos34yaWoU0Z3jEBvCDHXqKTrDBL9f94/eiYL6dft5h3yMgqntl7xmjpP\nKtBM+wV0PzLluyOzA42P9SE5K74eskeePaIpwb2mrRYapBvNpLdjQXEQxxCD\nY9Ru\r\n=fWqa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICldJQLwYMoS8vJtQ2seQdBOjd11WWvkZQ9XqmxvWDDvAiAXoJtUT5orUEGQZb98ugsxPDTPu4avAq95a2rPSqZfkg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.34-alpha.1-rollbackpadding_1540959840078_0.4326439363527188"},"_hasShrinkwrap":false},"0.12.32-patch.0-rollbackpadding":{"name":"teambition-sdk","version":"0.12.32-patch.0-rollbackpadding","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.32-patch.0-rollbackpadding","_npmVersion":"5.8.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-3cmkPu7ntR/z6kO2QcpVvmqvBquTbBQBtNb+fKt5KH+Shm37dhSwqv77MOdgGv593qtZ7s+WZtyUFyTLSbVozQ==","shasum":"2322ae37a1c2f08a61bae4995c4c9da1e12e57d0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.32-patch.0-rollbackpadding.tgz","fileCount":395,"unpackedSize":823396,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2UQsCRA9TVsSAnZWagAABwYP/jc0v/tXr0B23+Xb2BYY\nqdhF0/2oMjFgMHI5RiRAWYlZV20uAk8i037hx068WdzrQJhn/+clqDjFERv+\n0u2UQQO18O3ef6wm4JwXfLp/rDQUAgZgrm6lj+F6toxvLnU9l3YNLJx3/z18\nS+cjUVxEu55DO5WaIOyMa59y0EbWO6MZuAwT9rOFnbfTGdL0/SAEEYNNPmjk\nxKFD25xBqNlEr5ILbdenXUvNHnTLH8ofblr1XWBm7JkxLgEucKpGGacMp7SF\ng43RIbgYce5aIwWPgxS8aVW7+A41muUmYZMAhHDr2S3W3U0tlkwXY7+EFdRh\nCKUsV2dnWpytgeNQsLss0qJAFPwaaIDyD40sMNeq1ecQQsFzkxqdNnzsGeOJ\nr2jhgNVGVYpyDHyNdqo41IE88FVHGPNFP0IjWmzMNLL6TN179fKSM86pUZWo\nVcjj+E9j5cGdfN47A25GYSdg3HxHYQKiS/j4HWbroSDAU7HvI9hKy35stlXd\ncs0DdOk1AHSTsO8oHPqtqJWhDFkq+2k1MrfEsSTPONPjPCergn+XkjjLZvXs\nAfLmJwQ6X3giOwufmGAbTC18V984ar0kdCPaaAWvaNeZQ4UQwEuqx1ssJ72B\nnjFwkDTK4vnin1pCGK9SQ7gNnw8EkNSvhw7DQEH6CV3a/h3os0W6DzL6bFds\n87nH\r\n=iGW8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC2hGCUEi0qnPLa1imr35NQFBKbICQrb3QoeZjVXO+s9AiEAwjKXGrTy6M3dSbY22X53Vp+LL2Hh6jVSHfBSqMnIdNU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.32-patch.0-rollbackpadding_1540965419653_0.644266141783729"},"_hasShrinkwrap":false},"0.12.34-alpha.2-rollbackpaddingperm":{"name":"teambition-sdk","version":"0.12.34-alpha.2-rollbackpaddingperm","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.34-alpha.2-rollbackpaddingperm","_npmVersion":"5.8.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-Fc1uK+SLYbQaxgu1zLE0YBFZo03laCz4dtYnYN/PrZ2DpVE6MC/hJq/zOF9YJM9RNMnjFKZgO1/rlDcgL2GodQ==","shasum":"da39640d2089b17f017fc0cdbb1ba815b1a4a2db","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.34-alpha.2-rollbackpaddingperm.tgz","fileCount":395,"unpackedSize":825820,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2VJ6CRA9TVsSAnZWagAAY3oP/AwbXV9WjYAYkrLEAgG0\nN9XOIb7NTcWEurWiI6K4am7EObohedDY/aLQ7ldJkvoOYTgkVv+twivLpBPF\npT7f29SQMB/hjkxWzORa4HBpTRSUlNXSOOeGrwZ7QjaQXQL7PZ/VDKFaWmGW\ncLFK7qkERmQ9OM6VROIAKjQINgtRIah70LgxU8yR+Y+L5udcMtZeP7amFsIh\nrG4LRd3y3kLpQ6mcblqYzqH7h61+/YVY7B5d0DMsaRVan3meuFohQRGi8lz5\nMfTcJOOCtCprD5Rq0i2d95HtW7EZnAxOD770HhZOBtl9sLu8zbWLBSAjBS6g\nBo6ZHxFdA4hViEd0Ux6aCTY/J0YCZ73E5Hba2XYVT2PfkaE2mTSNpe/RAEuL\n/3mpa8kwIJ8OYY9pCKxJEZHe+QA0IKP8M1cgjUoFsUoYS5iub2UDNLt/2Bs4\nr8U2GewBL3aDa1UkkhJ2HQKcufg1U46RZPqVYwZrUdooyIWU3KwOUE2cHFjo\nhF5ErRt3F0oDoYQ8oWEXN885ttmd7n8Z8SCa37KrFoIvVk5si9sqeJPellVi\n3N6CDRNezsq1RhFXdHvEyODjrLM9bzb+GUl4LbEXIyIhOQzPISeJOammGeGb\naFilVh8B8/1mHWFGKwfnWWr/IiRLerA+OoutrbECWMs/9LfuvLrgzHLduy4Y\nCSNv\r\n=RKbI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD6aRqPBSX/7SC15eAtGOUNSanYysAEy8p4kcFHter9gAIgKBrBqU1Q12jzbqLjEqq2j0x1/lSDXGzCyPDnR3PoMXs="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.34-alpha.2-rollbackpaddingperm_1540969081273_0.6009182449044626"},"_hasShrinkwrap":false},"0.12.34-alpha.3-rollbackpaddingperm":{"name":"teambition-sdk","version":"0.12.34-alpha.3-rollbackpaddingperm","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.34-alpha.3-rollbackpaddingperm","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-DmP02MvqDONOb2tI5X8melLNV6NY5tM8udJ7mDLzmLybEMcab3oMw1kjkAlnFyvACmy842p322sWSJIdC1X0Ig==","shasum":"dbfcb4ee5f8987a2c41cf77e83477dbe60816208","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.34-alpha.3-rollbackpaddingperm.tgz","fileCount":395,"unpackedSize":826167,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2adGCRA9TVsSAnZWagAA0e0P/0dYtzlpRjx6XLlIVPFZ\nSsJxg6Xj86WHGghXdw6fWiOZxo7b+C6zG8Wxfos0qny6rfaPJSH/AAZSEdJh\ncVDN4iVIuEdVopD58jMTgcQSHMa24ZwILBLUl0zLiFL6nCyOWLSijpAnK2Xb\n4lGzDCPbr3cVmu7YCX/J/ERJwbEngP4mP3XE1i1fSY6F+o9mbmw5KLD78v00\noZNcD4V4k36Ep2m1xAyDppauTrmwGyWG80WSKI+z0bRTGTiiMuYhw8Bik/iZ\naoG49pIuj/QzxbiTDIn8yyg+fOJNA9iGYVvCaCPBiRCKt9QLTBqszm7kYWhT\nmZm58eHCEfsyocp+Ak6mGLSKgSSYCgipGvQpFAldGO7pDS6DlhWVf5IJepkA\nqap1+phYCLwTCP1J4wojiAfE52dfOdxFM9ACK9baOvAM1xViFS+JM28Nthtf\n+8mmtXOfoLQekTf1mRXE/hho2/5w8Vf+8/W2zdUeDV1i304gXjR2QqhZY7t/\nqk3b1tM0+XbI9xuPk97l5NMXVAWkDiXRqSwj9y9LXOVRgwHpXT9BH2O9QJ4r\nrHqpgqD/foET5ZdQwzAXq0CuH3BMdYsG31+fpV8DaX/mCOokQgJXz+QahKPI\nTkLQLtdFW3VL2egJLxRRn27pmu7utFykRq+yxU7X7eAF38fVaXGDaA1DKUCH\n32kJ\r\n=GN3u\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDghTbBXrGA0ZvlJh1nHzgSJ9zVpbWVB9bcIUAWhf6tfAIhAKuASdGSGW+COyngxZhpvxd1KwKjIXHsBQSJbYiJSkfl"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.34-alpha.3-rollbackpaddingperm_1540990789956_0.6093961920948305"},"_hasShrinkwrap":false},"0.12.34-alpha.4-projtaskflow":{"name":"teambition-sdk","version":"0.12.34-alpha.4-projtaskflow","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.34-alpha.4-projtaskflow","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-uDhbDDx78Fu62kIDHY+SUDM7MQEtgDtMdLZ336j2TeDkltEe/W7yBRaRWCWoHoc+y3QrLyWYDUXakhW6NmPHkQ==","shasum":"ca844ba0e8aa4873d7f509578f430d9e04644ad1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.34-alpha.4-projtaskflow.tgz","fileCount":395,"unpackedSize":827005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2oneCRA9TVsSAnZWagAAyJsQAIldMti5OsKFq5ZQCeyI\ntPOUOcJcJsm7PXZMNRHE/SLxRonjykVubAV5N9RXz9KehgHTdUJ+uhfJdIWA\nv2k0B98mvc9R8eu2e4UDEtG0N3fONDVfDLWt6uqKVKRtcI4PhKqMo9ge6fvQ\n0bxq+2Kcgd9Rbng8niryLk/MCPf6EAI7DpuQEkfrOAcoNx+X/cTIzPLSoXNm\nEbXJV8WBnCXNKCVIUbr28LWORUBF1GGuFxI9e7KqElJZlxlccOySEpa0TEHq\n7dw2he84nqlNhtBBuOk1UL29i6mhtEYmR4M35uTtlgF+vFMteYQMbkRrr4I+\nFlOYvM3ykeBimpaxraHkxMNotQbqBZJI+oocaNvv0qzDhBvzZBp2OLrqZPFI\n470gWfWom0IW0i6+EgxMqb3lIjEFYqQ7bHSh1ightTXTbedc2FeOBgTKIYJD\nT9kLAy3HKR8EixkUh+3lhXPwLhwzR3YXzJ26YPI1vskVrSRf6JuhlV7MYfW1\n5MLC7y1ZckSEjGJ5OaP9Q9LbbcToXzKUmsCHDisqbrhcnMuL3Mx7BmZ8UxGu\nAdm3INT5NgtbxTTOwq01TtvjHsfQw9sWQHTgTYkfD6bpetRYPbD9xPHbauSF\neW/e+VQ6tRozew0quCYTOce6muLZjOoSSHuUDesiaGfAeZ4nsHdAxsyHCDlF\nWcI+\r\n=dQy1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCrFWvt/u39Op1gqjvKfDFyd7ka+YUAWop5QxsE5PQuEQIgRSNdqDekn6g0jrqTXhK8GGJaRZjhjZUdz5viFoS0ohY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.34-alpha.4-projtaskflow_1541048797658_0.018990860184568303"},"_hasShrinkwrap":false},"0.12.34-alpha.5-padding":{"name":"teambition-sdk","version":"0.12.34-alpha.5-padding","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.34-alpha.5-padding","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-g82HiHoFFFYXl69LFlEWUjkQ14ZH4DZ6vwheTuNl3iVSl9mB6uXUI/7Cl4V8ocmT9T/WJqe2cPSYbl4STef4KA==","shasum":"bc7008cb41717da7e2f29c7ef255a4d330c6ff77","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.34-alpha.5-padding.tgz","fileCount":395,"unpackedSize":826740,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2pbKCRA9TVsSAnZWagAAwCMP/3t/dTUqlPzYxNb1npWC\nC9dKmZW3NxzshdkMG+3JGsTX+2K5D47qK0PrX/ZILZ9P808ZLTFYE4O2KdSi\nVrLg//5ZAzuzUT9zbs2bC1HsNke+kAf/nrEiioe0r090VynbYao5jSuUvmkW\nmICSeTj6oeAFvE/kH1JM9hn2rFyACLSt5oPWmyZ1NwB8BqASUEdzA1yKgQWg\nnx3hRtIziQVR19RG7luJjBjidNLEO0rQUg11J/7AJ7SpaSXbyQKoNbCA/L4o\nNFMjraVqE/PMnwwDKMWwTd//FCRXSzjT4s50rHjpWlndhAO3cVKDf6cZehoT\n/z9/hhTZF89tFe2/KqI5jeYwA8ZT827ujU8vREYwsIcUAX5YaWQv/snthYXi\nvX29WP8sNpGCLGXy2/eYR2u/bHjc7FXHDsnY7RSxZld4/Mbq2kn1fV602Ji+\nFu5UrTNGLz5a511WuZ95Te+vyf/rweDE1dEEozdTwE6AVUmxek4hA3pN11Y0\nBxWIXWG2hmBmkyF7fY4gXe+mTQ68CctnqVRVh7+KU9jDHNS2jxcndx5i1+65\nA+UZKAMFEMVsn8j0cNSdHLYw1eRWpNpLf35cXMGJvU4yRAdNS+UtWJHf9n8E\nrcstapElDNVFfbdu+XCkCv+3x12lLCVnZkDC2CX3vXS4e3dIPfa8ofpOjmV0\n1zf5\r\n=fUh+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCvmp8XHp880eRS7CnPLQzLWjf29wFsPR6SoBaNVqbLpQIgDRc1+3thmXFPSez4zfwRkOw2eNMJd8fllGxenqPvvlM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.34-alpha.5-padding_1541052106036_0.2748145423911028"},"_hasShrinkwrap":false},"0.12.34-alpha.6-padding":{"name":"teambition-sdk","version":"0.12.34-alpha.6-padding","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.34-alpha.6-padding","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-CZ04M2p/H2f43ngDfIGgTfg8HbpodhbconWFdrFBlXzDHlSZ/JA4kiICm9j7VXPv/jBBpjSD0jWCRSsoB8E6lw==","shasum":"4160995b2276226bb036988f944ad6abc2739947","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.34-alpha.6-padding.tgz","fileCount":395,"unpackedSize":827518,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb37qaCRA9TVsSAnZWagAAIfkP/RcaN8fgijYW5klxgtfx\nx52zC8eniZE7bBqRgX+dtHDSgRE+ykUTwABlWnhhDibNqkddmKY5uCusHVHU\n6bhmxrUL2weyiNo1DzIthnmAzz1z2xWCZ6CVjISqT4mWaPvFQEjT0TKm+d+2\nIlipbi554IEgEroAgn9grOYyPPGaTQyoSxJH4KbnlE6P0HMXiHM8iBncgfcp\nfUHqZZLlyka3ldZCCUneNQWAtXs+FrYmWlslhZ75lB6iMDLyg8DWDaL5uoJW\nllTdXudcUdmHq3TSB6+umuUcjgCg6WuxEwJG1Bpx4HWdSzLXVIQhiVMook35\nds4ChHUFfi6wbCiZVIU7s4fZvfSOwLpHN1Lgqim9yvIbMgFZLHCX9W1+fgP5\nk3hm25mDmzxtDQd6X3BsuJ+KVPfiZWbjOzwevzIYrn82xBnUCH9zQpI6wtmJ\nQbqBARhxtWsFzSLJj/ek3S5BQJ8KPCfL3PGCAjHbQA1yDw4ANQ2EXfa+8hYJ\nVWAgJZfUh0zm9Lik7hSyG/qsg+7ulRQfJYLZ8OBv55Bph9HSTAh8v3LBDi7Q\nffB/S6KabOV4QSuymaf9TccrDXs2GHYwI7g/kd89YTaaJaMjnPQ8T10poz6j\n3+Mvl+Xd5US7zLrjickSOAzpX892BDl/B4ZfPV9fAmdV6BG5CLTfLCzutcsI\nM87+\r\n=BuUp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDbfc7wGm3a9YpCVpDssOzu7CyJX21faJBiaA9uq9P0eAiBA1C4XwTV9B+/1ZKBUlMV6PnSHaCP6oN7k/FfF5CFezA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.34-alpha.6-padding_1541388954008_0.15116207275658233"},"_hasShrinkwrap":false},"0.12.34-alpha.7-tapestry":{"name":"teambition-sdk","version":"0.12.34-alpha.7-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.34-alpha.7-tapestry","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-icI/+z5rMwZtucOCwrIOMPfrCwS2RpaWJVN9E4CJPjbW1EagD9nvM1G0GndnYxJzHsxjl0RbXlRoCT6mUVv78g==","shasum":"baec19a458c1a17d269d29b6315186a91606b299","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.34-alpha.7-tapestry.tgz","fileCount":395,"unpackedSize":828841,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4VuzCRA9TVsSAnZWagAAWuwP/jzxeP/fNfU0gRP5T707\nxJ3jEDaH5EBrAA+fiL4gBU5XTfHBHXs26N50C0c2xRZkviEAUvumNgspLK5j\nRcPcGEsF0I9ISEaXjtHNcARIyJtg1VDK8/ZVv6Rqj+Aw4mLpBcPq6QOZiEzA\nQdXGLF1dDc+H+BqKuKwVJT6H2W+lV9BJejV+oB1FcpKSKIvOZGcXQmW1yYfD\nWM29YhIyPkzQAJnldDxGSyk2zAasrKQMs6rq3M5l5Y0dvtEU73ikWwdWouoM\nBfc0IlL6iu5h1jNaEv7AdKdbeUAK0YAwd9zCd/GjCP0/+B9iXge1ckBOni0T\n5SN85k1aX0Cvb0xZjpNKFc+F3s2sSe84QrE2DGZkeaTzOmZcOF2fI2e+MaoC\niU789DqjrrZskglhKBasr8cURHu9N4OUPYTRnn57znNPLMf+yZgP5K9j9D6L\nPpFL8PSKR3BNwfhYLpnAFtN41676meFqhOXxbdUUxCrUWqOf3rf+nU6l43RG\n4gNWH+BCzLZnEHRtMEZHHzLikYrx0kA15GTFIdCSwP1Oi9RsXYylo6K7+tiO\n8XlOy3iKwpal037FayR/q98HzAXJygJmcVrYiivYeBiTG5uVB8Gh+EmDpFtV\nL706HBuQxeT5F0YYQLevpkJZHCP4aSjBmTHMI1SlLoQ11y2LVsbNlBgyR4i6\n/nmm\r\n=lGX6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCLUfH/PaEa3XweO8kiQX/B5yhD2UjitP9F+nPfLe50kAIhAMS06Be+X9HUqlxKuKSjuwqDefmgUwws5krEUC2ZrhSI"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.34-alpha.7-tapestry_1541495730972_0.19441051634265172"},"_hasShrinkwrap":false},"0.12.34-alpha.8-afterpipe":{"name":"teambition-sdk","version":"0.12.34-alpha.8-afterpipe","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.34-alpha.8-afterpipe","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-MF28hMJYSKfSiUKPuUN5kepWsmDielt16C2/9iaOy9iVu2Nunr4Nrf4VRi5HCVDm0li1alyf4K9lsOZkMag5sg==","shasum":"1e4d67ea173c37fe0d247352f675fdef105d5fae","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.34-alpha.8-afterpipe.tgz","fileCount":395,"unpackedSize":831869,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4Y95CRA9TVsSAnZWagAAK64QAJR2Lvqq+Ry2jWl+nOvs\nJdIUznMDX0+XMgKjT7YshqxBaAXc7B6RP8njJvKLwg9oJTsw+9uc/JgPNimo\nbLmrHxgOaGZUIur113YShSrq6YDZMKJDtje5ePeJxdhntSSzTu9Lt8HMuHht\nWV7EdhnSrt+I4NdnC1Ie+3h4hX7qVYm2HA//ADGOHWNMBKFZLFSEnfODi9Pm\nnoLhGAaUshlw2dt6pNKRVPvs5c7Zs2UvefpQIyS1Sc/yr03d6dwqp0npNIzl\nf0IrDB9yaz6969E77jek7qOW4fshxAr6VRIN2T7lzCrzMxXy5CGgZhmRZ59O\ndNXIo6CEZNOvKpcQ+wIwCbQqHBkgew3DuXBXpQJn+1wj9ZHvmezmGEeGIkdj\nX10xgZndhu76a2djSZdOQX/yeO/1dlz6FL5gdrDHya5NZkyYD2DrZU2PLsOA\nMu+cG3eKZXXcTcv9UpRwxQnZ31/oUG1gokVctajZ26tFBtT5gYYPeG+ZMJPZ\nyqCXckCRbmXisZ7TMwFTFNfesKBHxbm/mOkTG4stdAoVHHFSE0zl4eldT4Pj\nhYLtVUYhcPeg1LZ1V0WyYmouVbk+q+bsVf09Md/J6EkvMzYOwMuBtO+x9lmB\nqgsRr7lwE978YH9pX8NYmwm1Cs9Z3kFCUOOKAJ5IrgVhU5zmEfUdiG+mRhRm\nwaRK\r\n=bU71\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHgQyOzizqT+ToVznYFC7feU6KhmoJxUXn74sRhs94ZjAiAOZjD9izMpBV4QF9xJRSnGvZ1DpnPwtKzrNcTZZlwLXg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.34-alpha.8-afterpipe_1541508984229_0.37379682753336496"},"_hasShrinkwrap":false},"0.12.34":{"name":"teambition-sdk","version":"0.12.34","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.34","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-TALdTnWSUkul2+jwh5PO/adxjwm43tVpixUZPKcKms0BsE5quwXpgkGVGDOx8NgSyTzmEPYcUsxYP53wzXdj3w==","shasum":"6c2322b78dc43190070c097abafbd00ed1817e70","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.34.tgz","fileCount":395,"unpackedSize":828527,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4oZvCRA9TVsSAnZWagAAvzoQAJR6EkXN+jc8eLTTMkWQ\nx+XVE+zBpmisXFAOsm8gKracp/gnMbBfIOME2fPKCMFyenyNQCLkD2eNjjfK\nshZnhxep1afHz2bSQaxb26OUkxbVsyevr0hg+QxZh+W680p0v8S7/1IHTnnh\nh7s7qZTGVH5fGQ9X7SutG7tsPupshuD6rt4gG5tXyTT4d2Bx4bur+teU00Sn\n5tlyTHHZGjaZFJpAUbQG9S2kq8qEuEH7DtMv8MNKAalVrydJ5icfaLsa8A33\nQrNguLlIMJAZeCkoVAFY9u63POvys71mwZKb8jxsFrunyxh2YvwS3aYLuqYL\ndmmmNq3+fjq+IzmcthBBL3pC66CEO8jAw/BKb/yUjcpk4IyJ8W0m8M1JeeGf\nr647a6vGALiJeAX8OxRXvEde9zMx0RiX4qZaNrpq+Lpeo2Zf6BOg+CPr3p10\n+9pTf/299UG4lklzmDHgUiK8CgxBRsiVJXIW12uiko6c8KGwpLD25fzsQmDP\n8iVncXBaPhd1KlIno7SYA7jisoWyiwtejQIeCahDZC3h5vNaAC1u2FDUC/OZ\nJiHEVUtgF3xtLU5BMAma25gjgB7DxklYV/tCmaV3eBQn1Xh2xrUen3vT1t3h\n93kug38McdaM45f3jU+w2DXqxAnPXXCB2k927lkfgB/H4ZHV/Ie0FT82GQaN\nom7u\r\n=75N+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCfnbDxziMTKhpZM1+rzdxrVYn5mT2qIZ/qNBLPhiCy1AIhAI5ujwU9EjBcc6goDsVDKCjnti+mjUZI0xrG3ZyZr9g8"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.34_1541572206468_0.6459672691451916"},"_hasShrinkwrap":false},"0.12.35-alpha.0-projtagschema":{"name":"teambition-sdk","version":"0.12.35-alpha.0-projtagschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.35-alpha.0-projtagschema","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-TXUBP+cpniQrIcjPFaVJre0eyq2cHj48mCVNjQ9bZSUl7A4oimdfd9vb57eUL9iVTgWltZA/9lypj8cZRZqS6Q==","shasum":"77144b24d2e6803b347cc7255cd9c18caea09979","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.35-alpha.0-projtagschema.tgz","fileCount":395,"unpackedSize":828362,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb5B2CCRA9TVsSAnZWagAASKIP+wQYwaoEmd/eYhTimTFV\n8ZFIwtcCt4gmfp79N42AePZw3oYvoopzAYgf01giobQy/mpUdPhuF8S60T1O\nUvMx9pog9JZm3yzfD5METYW+2KTWr8B/6rIqR0ckJXP21SQtG1ppQNNv5sqJ\nnmI4pFiiertKlbgRNuAa0yqf4seOhooj2O0sLepPKFNlA/oy+pCuZl0M0hZL\nscnauJK2avlm3QzapwshpfTRKep7YjFvGFCzfGofbnJiacpkTPlaflY+VDPO\nN3qr6c+0zQrAz8g2PzUCocdiFIGecWm+QTmCzYqu4+i9L45BK6kznlt3GE3F\nJ44KW+/so4EFwC+jyb6lNG3JblPimXX2m0KKpctWxVKA4XOTkf5RGwstfF2x\nE0b664gO0mBy78qmqU/yeqak70ONznJ0GxMgSDdjJb3ZHX7zp4w1B2sgDGlw\n2FD7L0M4ta+8J5mxhUQKhOoGV8yDUzD9lhDLRRW6wIU/JmULBCy3bcyrV224\niI6RviLJdOlm47eDDlGd358iFmqWEFyBf6fmeweA2ECP36tCEUWQZl4vkJ38\nrn3qLS/Q9RqSQB4gRmdFlTnacut+5mh9MJq7KJWS4YJjLZWMuJ0qrUxoqMd5\nWhqnMqWqzy5vpfUenJLt82cRssOy/30lK3y1JlXeBv+HaQOy63jaTGaMsgmb\nnhn0\r\n=Zs+/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICFEBJxvrBwcjHZO6lwGtDAJAq5rJUWrZD9IBxFdpmK2AiB6wsWoWcZG2vs3Uq7hczUko6/r9iEtG9ChvmhKZXs5cQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.35-alpha.0-projtagschema_1541676418044_0.3445836441653283"},"_hasShrinkwrap":false},"0.12.35-alpha.1-taskdivision":{"name":"teambition-sdk","version":"0.12.35-alpha.1-taskdivision","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.35-alpha.1-taskdivision","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-8huPxknpDqTtHNa/Io1AOn0R9zlWDL8ETPkeVKaXq5ObU7x2dXV6qbVBHvlXStlfI+t8kWiIoY15v5+RkfhFiA==","shasum":"0d7cb341cf2f941b3003c1771554a9b56c47536a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.35-alpha.1-taskdivision.tgz","fileCount":401,"unpackedSize":833292,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb6TcSCRA9TVsSAnZWagAAWUAP/3s1P6dbZx7dFgZO7XBf\nu+M9d3/vcx6eZJ/fDeassMoVpwPResX5ZfnWIGmqHXLSrVKfGsK6rUvzisZY\nkIVuQ3tqryAjKKYmeLnfrGzQEjqRonCnNE+nEtDv+LdV54ehoIRj1LWME0u3\nkvDa8uCYP1BW3Zgqg6FMNFt+wBrqFeS4/XKyS7PH1S0BPZ4fBiyIsTxW9NkA\nARm1t+74134Om5N6DlO1/sNJ0wiGBM09U1kM0wdhA0tDd/Wmx8RwoCZJU1w4\nExtwjL1aAT+yNK98yhboZx47f5Sc1zYSjXSf5TuPeAZ//bxOzFyNeQZoZN/+\n3mE6O8vTQESO10xAFq5IvQmsVFyFLcoKPR2RQWORETkMcBDTzTPjk5nBPkuO\nkLYCnzN9nLZhOaX31UH6BvePf05hEl9199IjjmTc1hi64lj/TFXHAIRKPxSq\nTMEjbaOcse9kdykR1aku9nyJh1OcMNjy2eQqfS8/xQg6k81w4QFlyIVtwCOo\nAV5D5Bj0XA4J1YznZH/WqItxS7QikewO3MP3mXeT9HlBcRsbEDQCkR8p8MaS\nSWLehOjmWExXLYTFzc5mclHAKYS9RhM7wyiXwkuLd3oBhg68+C1h4Kb+3sF9\nUpBk6FRVbwNbTy1NOGvG8reAOfBkWu1v3rpWYyT4cVOl4z9lgmtR7mkKqovD\nwII6\r\n=j5hI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIELVuhHKVTTBK/Fw74unf9D2La0qD+Y5nIBnkgGRUIT8AiBAuEZl67/vfJAXW/8VOz3/JZLZXF0gqZrT6DhNysp92g=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.35-alpha.1-taskdivision_1542010641947_0.7220226746014511"},"_hasShrinkwrap":false},"0.12.35-alpha.2-taskdep":{"name":"teambition-sdk","version":"0.12.35-alpha.2-taskdep","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.35-alpha.2-taskdep","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-vemiZHxWr+WipfixSLJ8fAtLAusp4XtCSdlbFz8VMJLtP5fSwGmHmkuM8ol/LzD4CyeMynkj1wDsgZdKF/Idpg==","shasum":"353fa08144d58e88703af817e98b7fb434e339e1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.35-alpha.2-taskdep.tgz","fileCount":395,"unpackedSize":829997,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb6Te4CRA9TVsSAnZWagAAkI8P/3Qi8YuRHA9nqEy4cBb5\n1hb/iev/YtmGXfR7zywaifoSEltNhQ9eFT9VPjG3l1pEWPFBuSawc+chTpt4\nVQJ+e/X+KOReh+Ofo65syTg974lw6BcAtLV2zt4/cHuW/dFlOJW9VrcVH+ua\n5uKV9TAQSRc8hHmwsQFON/YMm/DOI20X637eYAl5qn4ayMiBwFbwacubfHIk\nwkaI5+q1yS+9W3ZnRViqQ9vEhcP0qEieeuuVNxC5LymNKCEA8UIRLZ6keiJj\nxKgGFf6MzJ87UhKNdixO4y6pAenTnCJlNcsuyrZVpzWe9fHo/wJi6PxXVuEJ\nGavYrKs0wV0TKLpDb7lpsBMVIb0qCr6bdyIt8nBrbDj48WInKsuGv8jytUZC\npv14iK6+1lXSh5JFd4HwwXVYvxCtyTw7EONgj7CzIKx/bYzjuX+PFVNszt1z\nto4hUTJS8Q2GwvKJ1Bv9vNaQisqLB0kaSR2JgSg6DIOxIi2c33+U271rb/iM\nWVVuTptl0XUNszF1hVTHp37G/8A/zlp5DImx7HGrHsdIJYT0GoE62KTfxJZo\nURVOkFmxztKac92wDIwWT4DMtmVQ2YzWPpytcnW+Cidju8NLBGV/WAcSJ3c+\n1FjoB8zwkFKmq082C+KVOgaMO5kv1yYj04iC9LvveW2997OETiiNUbE91Avt\nA6e3\r\n=w6xm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDCaJrvrufLnHCirQ1GYeX+OVVvhv1zjtb7GzoPpGLAfQIhAPsC2xTDGrxYR4DZM9w32aMg1d8M6uNcKM0+/r8Fw00v"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.35-alpha.2-taskdep_1542010807661_0.8405873893278013"},"_hasShrinkwrap":false},"0.12.35-alpha.3-polypage":{"name":"teambition-sdk","version":"0.12.35-alpha.3-polypage","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.35-alpha.3-polypage","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-m+QCCKqfIFnNHB5VchO4GB1LT3E/AwHX+/gwE8li5/M66O2nAh/uokIvHW+mypdDpjNDfDcHH8b19f/xkM4s6g==","shasum":"ce9b6879fa833f43aedc8c83839c604e99f10c68","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.35-alpha.3-polypage.tgz","fileCount":395,"unpackedSize":840842,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb6kPTCRA9TVsSAnZWagAAUHIP/i4YVe59IsSKoYg0Qdd7\npk7ZhJ0UM2cZJZDkXslwSz38NyaFpkLwIVoPk8GJbhFS0UKjEIwJYkjoEnDg\nzoAr1XocJvvo9oieu/AxOTMmRsgwsWmnm+g+8MtA8Vs5zh4OANtoHk4bRJMA\nRASB3oR3rptZp3V+lH+43QRnbJNcOeYXrpcDjXgYKs8wcCJ2G4idbBKcOYUi\n/6/Q+K8V3lcKFTG3oKjBIxjxdBTZUAq5Uor5p0EzvsSnx3vlEptCF1WZR4rG\nLR5A7qB1ELoxdWV3DTRf4NKwzCUafWvz1ZY2RB7/3J3ZmRLgZv51FlaaLfjU\nWHIVwk9Ps63O72uZIaNFE47D5Lx9mK/L/J0Qh301Ljk/FlunQliIG8ZB4Rrw\n6SIkbeBnGUD4rQRmCPwNnqiwbzftXfEVPp4ePW2mnudeoOKLaD46LmGCBrnH\n2mguekAo18cdoDyijwM0D5p+oVkgYlacFPiEM+Gydd/94Dge13H0p/q25q7F\nIEpk9GdRYeQhvnOpXku0RCR766QXyxkOVm3cMcOJNXVPfCWIlFlS4WR9NJPM\n62MI12kNgNl3o4rSVL9leASbpjij/TJGC1bLeKWiR9ghgyB6HbyPuaEGKeAN\nGMAWuKQff6kMI5GA2AfcWBxhVzy3ItE0X0AcBXbMAYgTLpNWBQYc9vG52ZnD\nye94\r\n=vl0T\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHQHmYqKkqDaVBUaXpfJp0ADhOgMMrz5efPIBALpWRCtAiB5U2qmRNOLAI5Vi2i1jG0H48LTxj8W/AO13jB72BXoeQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.35-alpha.3-polypage_1542079442371_0.20901274796169256"},"_hasShrinkwrap":false},"0.12.35":{"name":"teambition-sdk","version":"0.12.35","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.35","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-tuc5u87b1LWocr7rXuaGFF6is28mi5bA1P2f8PcQEqEKiepG9YOGNCNh2FJpV/lJHUFRT/To5KXc6N16JzOA4A==","shasum":"2118b50bbdd4cf3359a00b6125cf67c35b2599ed","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.35.tgz","fileCount":395,"unpackedSize":829035,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb6oQTCRA9TVsSAnZWagAA2+0P/R7R6AWqYng2diG+nKkH\n8OO4YoDztutzwMC+tWb4w6Z7lr+oChH2SRp5KVvOgga7X+rNN+QBjjlDhU+z\nTb7cl/F8725PUMW/gkpAJGQxwCVNZPgU2iyKexoD3EtdgO5vf8nK6XRXU2aQ\nZm8IH3Y87OjM2qTfSEIB8oUTn80awRIWSCElLZlQWhX2znNy2ofjqTG3Fgvp\n7zZKzRQT4zPl0sklHv0/uGi01YVm5+baBmh0Si37PwnLlncuXFJryqVxSTVe\nsoIyS6iXQrIU3VTqJEgA3Iks3qz9mEJKImt4pw2h0W0G/5irulpoQkOL+D4d\nOxM0ZFe/JdbjK/xmS5Q2sWnqHZjHgFveVF5ItRZaP6HC/38yR8BepcybL+IA\nWuCeq91NmL5vy27Fg7iWHlMXY2V5d5E8m04NBSPWg5e1POYblzE/BSzWRmFh\nLlJc+XkQAWFkaQI0wG2lree7GerKL5sS/4zzcWVkcMRnJp5YOFTaULbjIRi0\nITK4c3BKSYmsTvRS5NiqAPHZqLeW4oiKOjW4t6zgCXFhfA8Z0a3V8FDaeOoS\n9aK7+W/t2Aq7mLh3nvZJouRYkxLuWUwkSzzF8McAhQ3alpxkgRy3khw/lC4Y\nvHYGh5aM2sQ9yu+9wBlin/iTjEPJ2oiNDd45JiABXroEoPPxkFimdG5JrDoI\nTHbC\r\n=HfVB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDskCyIA+N9Ea4b0iPVBsM4NIkyCDdOPNgziBQb2pq2oAIhAO4Q5C8YkVLvU9Mwmalf1QMywPS63USjm2UojBqBiUuh"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.35_1542095890759_0.38759183726240787"},"_hasShrinkwrap":false},"0.12.36":{"name":"teambition-sdk","version":"0.12.36","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.36","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-FeZfG1gONak6sftppF7mTuFLCnofO9+7MmfvBLOBlKPhg8zUIndvz12ecqZHb3mgSXo8QyZrhnNXxNdKgZFatQ==","shasum":"340f4a30ed8147eb8726ce3b4f72c440168a0744","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.36.tgz","fileCount":395,"unpackedSize":829037,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb6q0qCRA9TVsSAnZWagAAIuIP/2OmDABtqfpjHCMdY86H\nvpQwl0Tb4SoeroJ4e0QcOUKhcOuTCdO1oHCpvfqeaGp/dDyQeEiQbEveICHK\ncAGf1nQU1plfXIQrBoFp+wDg+IiY6HjLQfHivxhUG+muKKNfx8Jqz6k5jgWo\nRKm4ykcuP4pQN3r/3BWxJcDSc7ULILdrFZ7Vpk5NxkqXhc5PjMWuS5LxXnOe\nc+ET6jqJ5ov6zgAykvIga2p633I134SxnDLDUz9A4bPQez9VDtqq80CGyUQf\nTtupkk1wOPvh0Bz+AIQ7+JygXlnlUBSS+ArrpUyRPbDtYzf4uzJ4yBTNdMFT\nC9N3gGn+q2i1mK8RDRt1Eh5DMPPR1aL2AAXEUQNQwmsUGSbECDyE5fpHPGXO\nkteYTtp4zaF/2xNYadFTDRYl5iwlIHss1mqINqZuDvUHSLv2IUVvMLJl81gR\nQBtimBUh+jw2m8YwtypggyFHSJGTXZ2+rq7a9r6QnViEfemT10ctPzi53t2u\nTrSsX1wG5kzwiRJ9iUccGpdnHnmhTsua2hSgPmhyymYcz5FKq8xJGJKtZ3sy\nXjccXU00diytx5lkoB/TIuR7wb5D3JT70jxE1FQVhLCNJiA36WAHcyFobSl0\nCIwSqcT3BzeMKlLWFrJ49SpWf7FFCmdrEVgcyoeKuNUXkhu73Y8tPYQTIIXb\nIOZ9\r\n=1h4s\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBbw9/WkQQJa4LBS4V6OiygN2UFZKeKNq3NAeJ6XvddRAiEAiOcsYPl6MCdBRKh0gvwwQIyo2oGruMf9s6fW8ViKS2g="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.36_1542106409511_0.6879057687192787"},"_hasShrinkwrap":false},"0.12.37-alpha.0-projschema":{"name":"teambition-sdk","version":"0.12.37-alpha.0-projschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.37-alpha.0-projschema","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-z4qdflsV7F6ewSP2Pa6VWg01rdrFisBx8YjrYf5W8njK1kAiOdx6XFkOnOtBOEHWGlmz6spGFHwWXPWdw7MxQw==","shasum":"1eb57b69d62b7129f2a1905d72b337e1684bd93d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.37-alpha.0-projschema.tgz","fileCount":395,"unpackedSize":829571,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb7UFyCRA9TVsSAnZWagAA6eMP/AuveYs/A50M+Jfzrgxe\nrb9wl9WIIgGojfLqcLrFNR+PyUjHYjrpe8KuSCS1V+yvsOCXjgcIXgvqE9oK\ngVrepqlxZ8pKakhZcDVLsm2QgPwkz5ZbXqWpP6fQ/hw2778gw35s9LOPRmlk\nAlexheNE+uaZDlOLz8+TyDo6m5LDAxxjxnNn5Pa8+uz7vnFZUKoeB2mCMZ/Y\nArmSRsPB85jpnP7EAROlAQdHMyc42OIy5w4w+btFf+VvpCEVkhBFP6F9nS+l\nETrKvbok3xAYQo0owJiu64iVKpRnItJHjRLt6Qeub75ojP6MDHA2NAyoEh+W\nifWqPUa04vYnSL77DIIaBI/kJxzzvggI2W+mzOLEEB+L/odTd2vO4HM3Z7Lu\nxaYWngFsP8l1y2AMVIem0jbrdpzPnIMASw/qOQcEVbzpLyeZnS9dsylubv1b\n7vliwH1C3fkuxQeVaIweEF0QQ93x4fnp8r8rOkXQYs3edL/T1Tl22J6MIpwF\nIK+UCPDnUQnFIIkiP6pU4D4UGBb8XnT8QU4dUn2wsfpKOBiH2vWnCwm1fZYp\n5DS4WoFyJU8rSLXzDPVoE7yQyadFPvANiw77WHMujbwtNGdekTZuzuQUWVDr\n8vTYzGtWcX8mzc0pjxxNgCU+WencbhWTKSi0HBGjGRaFxbmKD434acJq0yzH\nhYzg\r\n=y6VA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFhD0ZUaI2xmxFffA8TlLHmLTvEGjgJ9Lq+OxB7YuD/nAiAZM6UI8+XeI3WYiBxr3FTSzV8CG8+PUagP3IjrSPqFLw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.37-alpha.0-projschema_1542275441310_0.6955201143835783"},"_hasShrinkwrap":false},"0.12.37-alpha.1-unknownhomeact":{"name":"teambition-sdk","version":"0.12.37-alpha.1-unknownhomeact","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.37-alpha.1-unknownhomeact","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ChLQZ0rJVsxO0Qqi/OHkyUmV1HbYSdzepvFKAwOTuCUYjZduDw2HY6+XErIKOITG1OvSsNVeywpFuu01MsFt3Q==","shasum":"de9a2692c6fb390addffd53689081c08d8c219d8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.37-alpha.1-unknownhomeact.tgz","fileCount":395,"unpackedSize":829413,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb8ir8CRA9TVsSAnZWagAA+nIQAI/IEsBpeG1yCyReLwmL\ndgR/Y8s87RdwEbO2BBhlFyOKDWUHAzToPrTE1xC+CUHgcmx7UuRZkgTZl4Tt\nXO0/l9i2GQTWLKtZeIljC7YjqJ3EtPwlJ0SXZwDopkp11zBQ56L6Qs6beoXa\nUXCh2nKrbJLRSY0xrMA1jg7URXRCDNwUPJOMQxle+x2ILOBlgDsN58ufXb6W\nwjFrBbLzXtNYDBw1ivzPlqFn4guD0penX2J89v86M+VrsKAgCdHvLGUbMeYp\nPvTlzSFHnmH+X1jcFr/gSDb+GCxAgRd1KBq2INazDGR/YBPf56b9kpi9ismc\n1cx65ID/+Cd+gNr5ssUo9kZGyrsXzcKq3JESPUqq91iA8D37VlieM9A0U/sK\neLWCrfFi7Q/yxUFnN5/1nP80RybFNFsRw3TFOICsyOu3v9b+VbjMtnH8y+4C\nz3TAgH0yl1bawr03++oZjQV6mnX0KPI7YxC7+C+y+1crGTHEROwsTOooRPSf\nasu3rNaBWxsTRTjf/KyZcQG303yrkLbEeJFpRO8ZCLJYfObI+B0wGxiTiosN\nmHi1xmmeayt/IaRfVKWcN8dORHUJpxWI3YR7Yyillu+uBLRCfbYoHLvKB9Ct\n2CrrgGJ6VMeaIrBW3P0j3+P9Sap7x81bshrGhl3lZ3jUu/RikIfZFWaJodcD\nWNyF\r\n=s95Z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC3x9yC14dqkPTQ7gI7wrybeukKTJ9JH2kerpfoXol6wwIgKIsApK+6BeTNUVxIsAPrHCr9s6KoOIVhUR0MBGTMl+4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.37-alpha.1-unknownhomeact_1542597371537_0.5284177500441651"},"_hasShrinkwrap":false},"0.12.37-alpha.2-polypage":{"name":"teambition-sdk","version":"0.12.37-alpha.2-polypage","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.37-alpha.2-polypage","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-KZP047tTffiXdnh6KDCzWgqFpEWWZwFCWvV1xu4v/izdNOsPLKI4pMgNn6rYLufvpG+MlaHyxvaFB+wzM4fDmw==","shasum":"db11325a23608a4eb93897c48fd6fee087547612","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.37-alpha.2-polypage.tgz","fileCount":395,"unpackedSize":841820,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb8nEpCRA9TVsSAnZWagAAMEUQAIrsjbQl6zjsnh+OU/rF\nlWTg69HVYJj67SnjNHTp63hLjpMuNBtnDXLXDRv3GoXAS7MnCbbZZyKi9s6F\nxYDQosMSBUZEIOisdF0ZOgQZTMWq5wks8nR3PvinZyYJxcqjyXfVv8dqIEk9\n16MDdaNmc9nk/hUWTl21bdZYW5aiqsrqh3jAytLI3XOGZ5O0PIDIpxTj0uka\nXv/Nc3k6a5cEAD+fXgCTY9ZDnteOB/WUgaNyQyUXexmPRI8UOruWn+EoBeAY\nfLDzuzFFMSEUu+ARZ9LrpNlyH1TZWx0+Pcf2Q1xg3S/UIq8+kuYqk+ZGTGpT\nynuGCxvv5920yMP6gBZQ8kxsCYpc2JNQ/yYjlkRFQI+q3O0XZZ9Neh5Wa5Sn\ntmdqg6nZ7hxlBDp3LNjxwR+//OsQaVB+GuJuU6jwPNPFsfM2Lwsmf6rfndic\n109vjYrjQphawbIDO2LZZx7u7+6dEtdkv24JMyzO7oa4FkgEYQ0bjSjSQmBE\nfoQBkmZNQS8FzRSZpkAq+vBdeUb1AwKWFX4VXA4eEB/X+3eUWX6yaPK/enX4\nHwzX5PSVOxTZKSZiS7RLh1M/3kVSiAY28Kv4YtO6/injGHxhM223p+YsWgOF\nmsUdWMDz9aKg1LG2Sh564utygdau2roxBZBnJF3HEURDzdAfVUxam1OtknMJ\nOUW/\r\n=LU+l\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDceoIODb/zXkXuaMb6ILTVOPjCrbMe7SX4i0wspx8h8AiEAg0uvLipOXtz0S7KaRDz9eFpIDj1v5RVEn6h7ee1o3Uc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.37-alpha.2-polypage_1542615336973_0.9059913349459525"},"_hasShrinkwrap":false},"0.12.34-alpha.8-permbinding":{"name":"teambition-sdk","version":"0.12.34-alpha.8-permbinding","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.0.1","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^6.0.3","tslib":"^1.9.0","tslint":"^5.10.0","tslint-eslint-rules":"^5.2.0","typescript":"^2.8.3","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.34-alpha.8-permbinding","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-DFZUTx/BMJ9ExRbYED9zHPc1sxstSO2NNYUqb1QErci1bQCpEHQaxh8QI3yKrC07Ewm9mrMe8qImymycKZDbOQ==","shasum":"b0d853a79d306c9d227d656ab5f21ce8eb908f3f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.34-alpha.8-permbinding.tgz","fileCount":395,"unpackedSize":827906,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb87HvCRA9TVsSAnZWagAA1jAP/RLIyACqULP6bPcwh2Oi\nAyPQaGqnSquS5X4c8EJSkCzow/z+V664y+ES7MDZrfqDJdGqrBRqrAWkJ4Vq\nJUG/L+6/MrtJu9cpjI86hXRNmfrb/ikqy9piih69jbH9eDVKmc2hmkDKExK1\n37cOrWIi0DoABBGA5Nahyt5m6UEk+oMwTzNuKH44tGo9iXT0ITcYPnD43dLA\nsT3zS6FtNPmjnCT6T7dN3AD2G/luUmh0Sga/FkSv6cVATiCl6mguv4/Us3ZJ\n5h6MG+rU6jl/vOfCP738D3pnldGt8LwDFMQvy7lXsp2n5N//N1Eh376OaoGN\nSACbO/m9pijrUhgNdWAnVm8RBEiC14okd83VdssULkOMTOOBvjnxRYS9BKM3\nkMQZMXZ3HGGhw1tFrBYcifi/TMnQGxY+hNxDi1pzN+v2vK/jXJXRI1SP3ABf\nU54I8QceMIz96L8XiskNzEcg+rK4HbrPuljo5m2SD4F0QefXYE05h/6w9MiK\nEiKY3kgAsay1vPtDHA2n9X+jPbpIg90qUm09aqgAHMpAWasPTXpvngl7HULe\nMJNgCKFa8D3yzdzwHF+2ZHTbrKoXTYzyWB8B3COKIPUjkZ/Jj7HqFOw0xkxN\nHFCSeWTOn1UkUcDuRuCNjuuhIqzPRfRkYGqChIG/Z5RmwvMhEAlxbw/uvygx\narV1\r\n=2nCR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFrIs15pfA5+e5sA9GIB89gep9zZB9baY3YSGztD8rFXAiBkb/Xn0BJkt3xHrrIhPXwosmncDMuzwYFh+MsIC+lWrA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.34-alpha.8-permbinding_1542697454782_0.12829767093530164"},"_hasShrinkwrap":false},"0.12.37-alpha.3-polypage":{"name":"teambition-sdk","version":"0.12.37-alpha.3-polypage","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.37-alpha.3-polypage","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-NqIbGjjTfjVgYz/OwPR1ZwMPqMqebIpW9ji5hdivNrdcdzbgSjNpPPn5sbirLQCIze58dPS0kf949OPM5GeasA==","shasum":"bda8a0c68657372340fd9436d4efd8dce4ae1fcd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.37-alpha.3-polypage.tgz","fileCount":395,"unpackedSize":842204,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb9kxjCRA9TVsSAnZWagAAN8UP+wXTtRPJTK33csenYTCT\nvxxrRtRqltS/MF17QFt4ZgM3prpdT6jU2nBQSbzl4p77fNQBKePN5WMJmS7E\n13NqL7ZaDD+nV5/EhFqHjh93ERilkJc23+z3yyEzvobrfSJ3tS+T0iiBteTF\nsHhTnqflu+ftepyXbLCDau/4/W4V3mcCbLq2CplwbzC3o1CAFdW6mpfJqlfA\n//X3dyyJ3wA25L4hXzZsbm02VOgFbmxEPMwdgQut/AfyWlh3e+fkZZV7ASbq\nS9qPIzPjYgmxVyzVa2f5RWD5XNRLs8BDY7qhkp50KVtI65e+rh21SZJ2A05p\ndqgN6X9nWA/mdM3IvtLuapCeLabb//ZNQTrDbkuO/bPD+CygykV9Wv4VDqDa\nGBgqDmVFYpVN+Bs7XTiRNAJKWWVGHdTUF44YJyn6D8js7TGdTvTewAzb4/3v\neVGMrQDAEeRWCCnfVrWg+YS9pHjBc3CbDKxajkSiyoduMbf/NEJr8AyZ5SQs\ndKruaE12D9rV2R3h8RNeCxToYVlwKEvK7uuzYp7URzpy5CHS+ILbHdEXyANs\nyC9Fc/Ju0I9I9H5sVXm+ZfkEHV96hK36NtNmxonP5+54RQ9MqBmJEX3jN+3/\nEfD5jrXXgU362UjbseW8dyuEapNqQHGddOyW/GcaCbc7A3Q/JtiThPw0+M1v\nFyyY\r\n=nZIs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJ4/ixSTka9QpEPY2V3C60bae97kf0bXZPbRiFCV7Y6wIhALqMdkBvWZeIR+fuW3Xug043kI1c2Dm3J/Q+Rn3L9n/B"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.37-alpha.3-polypage_1542868066626_0.27561873926192515"},"_hasShrinkwrap":false},"0.12.37-alpha.4-flowing":{"name":"teambition-sdk","version":"0.12.37-alpha.4-flowing","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.37-alpha.4-flowing","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-B7qB5qHw5yE3T2mpc9l0JasqTImIWPqh7EZmn20LgpnpIU4/z236+SEyppJcyU2U/HhXZ2fU6yMvp9REhP1VCw==","shasum":"c06b0509e35f9a5f997952f156ff2067887786f0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.37-alpha.4-flowing.tgz","fileCount":395,"unpackedSize":842412,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb9lCICRA9TVsSAnZWagAAxEYP/jjjFCT2Wqkr1ZXE0J7f\nEfBTjsGLy6z0Wmxew9kRuVm2m+saYcOltNcs4hW/cjDN0AZfuzJQ3VOyZOgz\nBPHuOHUtt1VPdA2JSN3BYNa+HVOh+03xXgfhU+VzvcETLgG0K06zpBAMcqLP\nwjR0XGCe5g0ku0my1H8WShGFozfd1L+eIcR9ze8O22afC//C8HPcTRsBQKGG\nr9p+fQ/ZQEU/g14kB6m/kQlj1i8KLk6lrGsIhwKLHKgxkUdFhMncbB72naxk\nig67xI4uCBrubDJc1bauEEA3e18Qyms5jR25CqzfIMDBzquVdpC1/9XiV2ih\nkLUWm2drO/pL0dZ6jSaKEJ52nlb73+FUHppAXnyv4da8bgOP4LTASviuj5Lu\n63nm5mpOi045V4SIsFI6Ao5XqqsVLBp1lzd7C6bIoeTi8y7SijhWpqDq6HFm\nw4m8i3mM/o/l7yVInXVTjITUZbZxyiWKn3300A9l/ErqV+5Zg35MmaeI7kbW\n5L3X/TGiywS0QagJQS81vvr8N1PqzGExlYpLvjG/h2aqCaZjiPQ+vdjMIATY\nqD5OMphtexjEaNIsqtrEiB1/kCF6D5UNXDxiEJ9ULA0/OLbgfQGzo6lfQlBI\nACtmj8LW586FWuXpfNtStX7K0MtXx7RmZeR4tkotuqvhsy0vIPCkXPJPFLSB\n3aJv\r\n=US7X\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDQWTu25W+LZrGbXI6sG3O2vD3fzXPiXx1WL6mWb3lqWAiBFVQG5OvVEnqIIfQvB6BrpFpp+c7ucngLacfM2DYwHPA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.37-alpha.4-flowing_1542869127794_0.8046640293114451"},"_hasShrinkwrap":false},"0.12.37-alpha.5-sfccf":{"name":"teambition-sdk","version":"0.12.37-alpha.5-sfccf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.37-alpha.5-sfccf","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-JD7pzBZOxniTto0siKdLIzb9N5PA+Evm3UfO3AP19mly5lZc/FITZNHrSp3PpCgUTvh2u/6KIZWMy6+zA/V4Fg==","shasum":"3b283de385e920f5d68ca7f5de0e56f86c4cc7ea","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.37-alpha.5-sfccf.tgz","fileCount":404,"unpackedSize":844741,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb+tvjCRA9TVsSAnZWagAA/NgP/j05OhKkuC66I8LwHuOX\nOIPGEH5rOPYcp4ObZ27pQDqHkNom/Dw5/8de9cUYEcO8dyQaIKk0v+5A0KGo\nTPi8bu8rEu7xCmwqhUFOCYYyzHJG6bzhrju6XzdqM5oSq2np5iGREZWE09Pw\noykU/3tlHE8qBQzKg6KT2SXo8JsHRJLI7Z/7c1qQCvwpnkoajFOwSV48dtwe\nCPeE7QFbak8adcrAE+hT8QZ3eQ2yFFwtB5peW3NTQ2o2EJymTPNOXmc0GLp3\n1Ax2KxnBQRPtzsWzzrosACj3d8fEAA7TERNz7EcYx5kLmtDvTeW/W1X3JMqF\nqQpeDOkcAfX3YvTfZ7hEnKdSLUmznqBexZS9jDu8d6NNB20i95mRBReC1C7v\nx6QEJC/LFupEQTkNJFfq3PbYyk8m122hMzrfnS554r3GJypmehIjde1NAHSJ\nWWUmV2oFWqC+tMyB0RlahKv+snkHnFTofSTk35t1IyhlkUiFevmV9zT2Q+Y5\nXVJ3JVdLXzdoZVN5zRlL/bJpdFitZ9KQkyZIEqjty77lXmpd/K7r10BUwyxA\nBgKgh2KhgjqoiP0QRB43tKVwb9ExZG8frphDLinrKcx9uYjvfMQioyRJhklP\nKeBiIhOLQ8u5EO/gfOLvEn1u1Pk4N9Onw1Wnkq2F7DLpK1d4+Tnah0Ctkmpw\nUjtO\r\n=jCTa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDrT8+Hf+/S6ln26ORtWOkTYAWlOE/oK7jJyrEcgk29IAIhAK9rF7vkpkyjM4kwQKPIHL1cB73gqejiT8gmeJfHEHq9"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.37-alpha.5-sfccf_1543166946950_0.3227882222604339"},"_hasShrinkwrap":false},"0.12.37-alpha.6-keepflow":{"name":"teambition-sdk","version":"0.12.37-alpha.6-keepflow","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.37-alpha.6-keepflow","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-hIQn2XTt4hkIOxNCsvQZCB3kbirS+8T0sO8EyoIKgGiaG0+xwUJOLWbC37PyXoepwNXVFcJ3uuAa4a4AMsjmng==","shasum":"29927687275e90d6372064f2301b82e339c686c8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.37-alpha.6-keepflow.tgz","fileCount":395,"unpackedSize":842433,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb+t1ACRA9TVsSAnZWagAARLMP/RIvwpXfhZT5jTHr2P5d\nHadwK3YtQpsJcfnx48s+l0Q6TIbppAz4i2qo1TdLDPeg4cUX+Y14pZxbAMm2\n+QKHjiqveK11MQcdSVHHhKr7UxvGVkK7ks8KnhZCS0eH1PLt8+SUDMjdJV+w\njz1COMKVZ9uMQS5AXeH4F8cDrA5tawHf3Er1odYfuioSw+QnHb2U+7nOKsDv\nT+9rrG08BYEg8kUrr20Cu+5JoV4OKqVSDxneR9HAmcipqqH7h8xj+AMibUMP\n6a1PNCXc04Iq0+UXhsUycAQ+QHHZKJEGmdQNugBrR1PyBpTN5L30jlLewhuJ\nfWMnLZztlhv7TDMH2LPYtl3+BjV6wVkr92x4bEgxy8owNMy4tkJ1fPjSZHl5\nCgdnGDocO9sN2tdkhFC7iNCphONcEJfjjEHd7m9puYwU8juwcfnO8uPIP9a7\nB02a2KXsaOhjCFQej/UHl9XtHDSO9ycK4PJZBkyb3TLSrv+hmZzdvVSo2KmP\nIYGDnS2FsA9sId++Xa8WMHF0xc7JoK7HKzgPt65uiVQythb0N5G3+ci+Gg2J\nICCGaiWfBkK4GUvkHAF1YrDHvpV78RNoS+QDqY3SFpuCoiGpoFRAzE01Tlkk\npKUt0kx7As/rooow41Zk8jsqo8FYKtPAG9d0HsKSxDg7MS0nK0IPPIKqNoM2\n5Er6\r\n=P3tV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8sIP3ya3xyQYXC6e8Rnow3+236+60+h32Yh8Rr91WKwIgd9D6e82XJxCyVqFo/V66a0Tp66XVxwDKuAAChCm9ixE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.37-alpha.6-keepflow_1543167295276_0.2702492789062876"},"_hasShrinkwrap":false},"0.12.37":{"name":"teambition-sdk","version":"0.12.37","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.37","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-kg8B6/GraDjFWrJU1wsLBGmZn84a1UtUPylgc+pnGkw/US7I99EQhmbXRzcR47AK3JXHypl0/3ukqTrZmHoLjA==","shasum":"ba5f4747bc12a6dba554682752b9c0188972a3f1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.37.tgz","fileCount":395,"unpackedSize":831743,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb/hKlCRA9TVsSAnZWagAAbLQP/Rkn8EmzPJLPsLXzDDSv\nVNQbutjNzKzie/Ls7gZUVhVfyj+7E2J5FmhTI8sRqXOr+bHvf3T6Zvxv8SQ4\n9KJfDhFXquc5kY8vTCT8ZOhLVK0xElz2XbxsuDP7W7v6Gxq/RJ9zq6txzw/d\nstQUWaEGJkd7uLnW3Staf/sgMkuV+FiISHoWaOqm+YWhyRrs7NCYdUOpN5ie\n4sTtIHe+BxOYbjzVsGQijVnxiZnoIHOx9dEwG7V6Y8G4HVvEZjn6LSsjr+Jm\nANFXlmn+8CLTvTqGptTGC8/ABCH+hR30Yo8TXWslr82N6LIwKHvPIciWuuXW\njXIlzt2nihQIvyHmZIgEWIvXl4zIX1+k6e8sqItR+Fv3UhaFlj7/tel06V7H\nrZozflYzWyJZwVXChzNN+cuWx51B6fMdw6M+YtjbIs4eRKplIdX/PZdECyUF\nlbLVuc3PxeYl26P5bpFRL5K81eGcOu1xtip64nSRPiCd5D9utJXRJrISeyDd\nvMo59Co421EfLRC7QEXsEc9CpsNx59tJnm1ydXqby6uNzsh1HSVlDPByVT3E\nXy6gbdLMDsBRkvTjoRZfP2jCgAvLPI+/kjzk4pAcWqIWcGrUzXzFcygDDJbJ\nL8Hb2w7AGy7B2w9uk+4rqeTcRaR9ZPbE0a6JoTMRLUCz+m0tj3w0+JQnpm2s\nVP4B\r\n=pwYV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDVn0ZrXY3rTkhQzfFd2RWBeIEPHS0UKO4bwq9/nPqMywIhAJdGEfyqdU3aEzhKN5hdyTY5NoU8Ah4FBes5THacLWLw"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.37_1543377572198_0.4394734012431445"},"_hasShrinkwrap":false},"0.12.38":{"name":"teambition-sdk","version":"0.12.38","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.38","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-wJsluspcF1fssOjXEmEKeKE7tIjne1mL5DW2W71yq8CNeAYe5VqEtfYg64WW7OjP18nQkWtPXgHEWo7MAyDjew==","shasum":"0cc9146c847c3dc0a9c0a4e920e6f7da95f5b695","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.38.tgz","fileCount":395,"unpackedSize":832328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb/mbsCRA9TVsSAnZWagAAi2kP/RsgT+EEA578Jj6plyeB\nWgoBBMgTFnTXwAN2ewPLMnaKrrDFf+OdrvqZ8qPHae6k+bFxVmr3MkEmnORX\n5/vohQarMY9+80ChZ6tZsq0RiEcheMEbeAjhgk8fkHKXZziF68Qq4OaO29Sg\nhsXxk7+au+gK+1mclRDGBt3xsn0s0FgFkAtj8Q48coeAF4RhyNsxNTdc26bD\ncQyvtdesqn9ouL2edFpEEqtJ1BqiMuaS6BROHAzUcY0KpoXDWXScLHiE+Jqg\n5bWUntflVIXGxUxvTQcqRz8hIcEMRhgU8+FZXAgMHueX6jEXL74bRGGHT/1K\njuhiUlqKdEogGM699woSn7cwWZDJP1+pbXC+QZlH+YqhGuTVdqtpJ/45l3dM\nRRl1c0ZYo3/akbD/Qybb40ksqHMlp9WqxhzWlKs2ODlrYAeA3j/kxjMKMTFN\nIzAaWOGxM2ZdvauCXyuU3neQZacrtWAZ/Ioz1WJg9p7Fbqf3kzPh99ViVb59\n8/XltbEiLgPXapU5Esa9K2hAUQpoQ423PUXdyedUHedF9YOpUibEBtipgTpv\n3IGoieakP+DVBB5UOQg7ZmqMn2GLqzsQWGkJPgzFAT2jBUdnsBAtad4gFBG+\np7IueMNEVWbzv0Xrn2XT7IvVLuv/lgx0tcp/Gvp0J+y3cjUjtVQJxPmO3lI+\nxUc8\r\n=qsHj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFPh4jUDyW4n//lXddtEJ3ZeZH370ioqIwG+r9bQDSBcAiEAyj7iE82MpsR36v0qYK/O6b7L48ySVy9nNUwNshUeTx4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.38_1543399146978_0.26255028421597926"},"_hasShrinkwrap":false},"0.12.39-alpha.0-flowthrough":{"name":"teambition-sdk","version":"0.12.39-alpha.0-flowthrough","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.39-alpha.0-flowthrough","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-5xbTaYwfIYYLwl/G4xU+9hbGbKTgqgqzaJWq74PX4hr47ZSGMVoiH12YBHNOU5WGxY8Tq2lFdNDZ0qeWXza6Aw==","shasum":"d0b1d14b618c7455f249128896810dc4c1e7c5c1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.39-alpha.0-flowthrough.tgz","fileCount":395,"unpackedSize":844828,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb/y+oCRA9TVsSAnZWagAASCQP/1v9+P74Wo9NbQamAV8+\n36X4MbQiiZRpdhE/PYNkMR6sFyLbWdv2d27bVP0aN/Jx/fOJW2KQ9f1YZrCo\nib4vf+9sCJ4T64ONWU0eYHiIRxIUKTJsM5wAfZ49qgata5gidzpflDp4QxO3\n635xBqBGDPT1v9jcpqVu4w8fiHkJAoyJXlxOjiXGDe6Jldt2CTuOLD65++mZ\naiqWXsiUTRN+uV0cf9jvk3pF+dVyMSxexkM+4ztL6sFDdcDXUZLPHwmPf+Hg\nC9/fdP2JW9MV+g7FlZa3ihPGj+TIIfEe27GPVn7EYlRawQYeXTRiwLAcd93H\nfJvwQig7wz+4absgoHYVqwX5Maexne/TV1b/r2UyzHl2kXlmOFWvmmjS/lhF\ng9qPKWi3cF5wz6Vr5qpSQ1ocx5PnsxKX6VFX/1cyxmQSlz+KInisDFN9Esc5\nFaC6aEy0nXK92AqWZSJUHnK0l/z+BdGYzGOnnJcJ8pmJ0SAyO06PFwOZUuhq\n0W6JmBs4OIdEX+DoMAxU2B7FF6SYtLat7AKOq0IwJWhId5Kpncr76cc01Cak\nuKIZWR6HcfxmJY/ZdhRGsvwKKLK6FmljLrQtn8Jqp/avfMG4WTsmHeLmd1C5\neXHfKv3+SaPPEV482S8k4+PCJAt4Zvezlq6DN7PSwQjWnqv+Ubqy6rpc+nWm\nH6y6\r\n=JTDM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICZn2n6rHX15nfTl3iwtbiGw7vEbtZfU0/vaNqPdySWvAiAwfSQgdOADP8o+yy/9QGEivKOkSkPujxUX4FJF5EGXHA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.39-alpha.0-flowthrough_1543450535564_0.02387837121879155"},"_hasShrinkwrap":false},"0.12.39":{"name":"teambition-sdk","version":"0.12.39","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.39","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-f4Noz9nQnboKeJvAA2C2hHwOw1CzxaTvBPuxxox4bqsWaN8ygVOrevjDRsdzSnltMkuiQ/ut7sQYe7QmGnZrDg==","shasum":"7c1cacffdde64253af0214f60f0c3847e3573b15","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.39.tgz","fileCount":401,"unpackedSize":837074,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb/+JBCRA9TVsSAnZWagAAJscP/jEMjJnn7MdCH1lRDT9R\n8HDufw2Bm/ogRQiZrK+XgMk7/lEw/3L9wlgS/U/UNON7ihUDCfPkwucsvp6Z\ndboLU/hYR84eayTFsG4yzFsBROWIJaHo+YaCa0tFfSxg3lqdBKKGVAoRNnfR\nc2NOWhuVTs7o8wFD7XJjf/85/kvE13/HFX0GkKDB73hvO7awKxIYk5J/fs67\nmAxmypqe3MfR4rxTic5GegsswFFOmDWpxkp3C/y9DBcuEGG4I4zPotfSyGWu\nJWuyn7bjcT3jJodpF4FclqUIefe1Twky6jtDVvyEFfl6UeltTtpommYYAayp\nLGVFzwS+r4kUgeSza/kT+ZKhsN1Z086RJHpcHRaU15XBZ7W5zxoLMn070D7E\nbYSapNyhsNUsXVN8PzZfoESmFF9QkKkJ6UdAsZr/Oa3YAuWt1JR0iBCAjDfF\nA+tu8r1GS8Gt8GrPO6jIrn5LnXN3V1IkHZIbKD6XS8fHMp9Mlq8l/fz8loW/\nNXKJSOpNbbwDCMO1lqr2mz2bi/sKJcB/bMrXnFzyiPmxJ9Tx8ZhB6dEIt38J\nNLqFukaLHkLs+X4kchHBnMAbHx0xi1YY2XsF2s5C+aVf6Pz9GFCFmHjb4QuO\nwNpH/jA9vwTyEaw2ilaiXKQmHTeNM1yupXOjLprRGECpjob2jhBXiVWE576I\nmAuv\r\n=Auwq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAljM8wWYg4ML0Zmmgn6X0wPq7u8D3dTxUHZDKdrg2LsAiBUbc4uqcXE2BP6bA5SCpnyopyxrjzSYp+IHY6Ztlj8Jg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.39_1543496257050_0.4600059505621923"},"_hasShrinkwrap":false},"0.12.40-alpha.0-permbinding":{"name":"teambition-sdk","version":"0.12.40-alpha.0-permbinding","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.40-alpha.0-permbinding","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-pca/d3laeevQ+0goTL5q78RA1HG5CCehU52iZpaCPf6u1gZELSxzQ7Flh4shHzvZTDwNajo3gk+Gz6YIjUhTtg==","shasum":"6ccdf775098dadbcc684deba5dc3182b0ba13cda","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.40-alpha.0-permbinding.tgz","fileCount":395,"unpackedSize":832810,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcB5xuCRA9TVsSAnZWagAAOBEP/1cMi91uqLRj/HPytr4Z\nqrfirthM01tD7mRzq0qhmSefeu/Smn8kFI2EgF4NF7zFSQQAXuZG2Xc7ram/\ncdtA9uLFNIwT5TMpR8NsiJQonPVIEzq1kWvaPoGDx35qNBp/paPXHZrkduwe\nKI0uJWYP7Li8yUloMywrZWhT/jycFn2+yGYL4OmcUF3hB4kOZV+XIpbRgR7E\nP0kNKbg2HH7SLHtp6m9+GyBr2ZjUWoSj7eiH5cPyqkANi3/O/f4ptLoxd1dN\nIo30fzvM5a8HyNhg/zz5CIBmr/F8AQfCC9hv5HzB/EPXa1OA++yD0s0HZplp\nMM3XqkrQcX72m7U9K6iYxoMFdUDcv0HoCWIkraf9QARoZZb+ZLraz8t0sWkQ\njRPhfxMLS6rzHTHy611kE8Z3LX8DD85cyfqV+HFDCloJfhmljLC587HFeSTx\nPCe7+wPhpZPBY0UkMVMX3Kjm6QkIabgW88/r5ppo37uodAmiobl34nStHoF6\nJvh7foY/4CAzt1DP8YS47wBD3HAOZGRq4bnDqoK3mSp5fJ6GXgn08y0AhJyX\nXPHJtdG0JqS2+IsMyrBQTeTmLJEjGlR7uVaS+HjD55WbkhjjlxX2vhRjeRhD\nu1MkVTsZieY+Sph39saD4p14+jBIoG1WFSh98L+oHp+f71UpmV4xkT9rQVw4\nHt0Y\r\n=zRJp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDaUEgaw2ItKGhTR0EmWEv5u4wr7E8nZAr6di2V3MqwmgIgA0nZdD9ICx8DQ/onBQ28IwbRJ9Z0/v82C3/LOrrNfPc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.40-alpha.0-permbinding_1544002670238_0.19974778086301503"},"_hasShrinkwrap":false},"0.12.40-alpha.1-luckyflow":{"name":"teambition-sdk","version":"0.12.40-alpha.1-luckyflow","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.40-alpha.1-luckyflow","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-KtLXvXOszRBXpCmBWGrcr9x2DfnDob4ej3Eq12wpQnMrjK3naIdydoBiHgCg7ROegDJ2aMHOBwlUg7JQkWHr7w==","shasum":"bd7913635f046a4699d35e4ea65e739c27f72d69","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.40-alpha.1-luckyflow.tgz","fileCount":401,"unpackedSize":849572,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcCQ4eCRA9TVsSAnZWagAAnVEP/1KJAP3MfVShyk7tzeL7\np+Z8JCytpqRmDjA9dmxmoYrKBNNg79rxAZl2xvLQZIvxu738aAezSysgZEvi\n/I/dddIg84uW7f/4GHiaM04wEd1oZzK0MDbH24zy4C+r1/JYI1lGhCLAqRG4\nFiowg+EybVOw0elQg3LQ2TfwhEi5xvfm7UQvLgrbLkK1x3+t+QggoxQpvtq5\ndSwZWBRsvlBbDxzhGUTqC4sHFCuX1ynK97l9eOMUlhToECH9/3yZaWABm6nY\nIUaRnQH37if7pqpNjp35DM/5IsyxvM8MRfQnSM7GJSNjrZRugyEM+4nTDpsY\ntuFUXXAmU2kWeNVRKuYP/d9iHtw1Ir9E+xXF71CAboWJ885SgLNQpJoOHrZq\nvqWrjbLj1/iBRrMsYOMgqY9waU+gywg2YtjJQjKPEjF5MDNEXOgXMnCCZHbq\nOron152/Ys6Uo/q+JeoYKArlyde7ZsQ0UP6XRsOx078XgCntb5dWuTt+7zNN\nKEwWzfm3MjCKpTAstqDztv3Qwopsl0rNjr+rh95ri2x+V9dfZOpZ5D5pllLW\nNSV0llilIXVUyrEhRLrC3rw3u3JR1RULk+6ApX7YpAWmbQ1GCxpHu1Hmh9r8\nk9STmYfhbvskUxd38ql9V6GRMdij8gQx+330VXLhuif/EMUEfNNM14ZjKOep\nQhry\r\n=qltr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCKOCo/CHMwflDVYlpqGLKF6497Y5FyXB/pWwO9wNhStwIhAPBQLBwEl3lO4GUcdHHIu8aNvbcsKSbpZ26pKjcor5tk"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.40-alpha.1-luckyflow_1544097309312_0.8122845747376872"},"_hasShrinkwrap":false},"0.12.40-alpha.2-projportal":{"name":"teambition-sdk","version":"0.12.40-alpha.2-projportal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.40-alpha.2-projportal","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-gIhuXYjl/HlxP79V3gzk5x9xQVEwFOVoGAxWANLMOmXx0yYQLmlQAcWcBxUi07THnkeLxtbmumhLvZV3XcsJeQ==","shasum":"f1f1aa204cb9ff2a108c941a0bde16efd6e7ac74","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.40-alpha.2-projportal.tgz","fileCount":401,"unpackedSize":837113,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcCmK5CRA9TVsSAnZWagAAL5AP/RuTHuoUp/sUeN7m6eXT\nq5rtdu4iyNE4iqPESQbHCNCH9iv6M/QptKklmpJTh3URsyF2oDmIGrxgvF7k\nuZEtNN7OBcX0ENddHu5+RHxNvF8crKUPuoznYrLx0cPZixbmurHcsxz+ZeJL\nCYW+GJied0XH4gKZzDeX5+9om46YRo8FFWaJYAAN0Kg+KZ/IN4GJR9qadDD5\ntWw+RJStYpGk4GC/xfJw03UyFovem7LPJt6YQkyPbfNyrfnqa+du1nrVwSCd\nKPbFKzl2GV5S0VCjLz52DpMJE4G1pEqbi1QKLLanoFdzHDDRZwpKLX4/luiP\n4ZqkXf/Q6Ocz52Pr0513marYuitnTNLO/ZFapSfiEw2SwUhqEcakmV0RFk17\njWyz87Yt7Mou896KFd8KrGzJxMihb1AVhPf7KkSbxo10r7gD+aysMviGQ3oo\nW2X5rkwLpWpLiIzbzMeR3p71KOgttSxPSNrK5qxlqp6qLY+fMPxk6fHwGlGK\nz9equJh/u3C+GG6paYUiOFhXOQrvbOsxYgXLYwfG+NDMTg81CT3e3E80ftlB\nCpoqNiPqvwctHbKdB/TC/5noU9w6r+Eg0kuSVDTt5By98pnG4ARLg5JHrM8Q\nm34QGm6cPnFSpf8Qh+nrXrEZYYQKLmmgSYQoQDnYbeupH6gEKlVZF4oT3Hjd\n6R9V\r\n=hGKb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC/ziKK8qvAqyeQ1XksTy+1B8TNCkMvRmwzBy0rbuf6NQIgS2yhmX+/0vjKSEBCJCPFf58kTFmw/P21LClmSUH2OgM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.40-alpha.2-projportal_1544184504049_0.5079167194951966"},"_hasShrinkwrap":false},"0.12.40-alpha.3-objecttype":{"name":"teambition-sdk","version":"0.12.40-alpha.3-objecttype","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.40-alpha.3-objecttype","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-10uREOleKNdXcYLeoe7U5OKV8K0PAKqcjPljGzBAENf0CovrRFEXMR9n8IZZOe6ibafi7z7zGdgdhbO/nahx0A==","shasum":"d40a1b97c1b1c9c1d626a5c9889d595179bd8fdc","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.40-alpha.3-objecttype.tgz","fileCount":404,"unpackedSize":839468,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcDdDHCRA9TVsSAnZWagAA5IkQAIFvMGU1c5NLS+O/lw1g\nOrOS2dJGLqf8YNuoaoIuClTHXxEs4oAeSNH3fckya5jL1plqQ9ZsbANubT+O\nVaeNz/E8KTN1OJYtu6CjCVhuww9Xm13/VoVgmt+x1MiuHi+CwLGpyXVwI0BO\n2v5eK1V9N1sqkL5DhncbrNSql0SHuiMLB3tA7jB5R1OPyGKJ4GV36xAx/9AN\nzoZmKWy77CpS9gD1psHTlWblfbnbwfwr2uMwydJ4iHx6jLhBMaObRY7eNTS0\nEL+M5Y+AOyj2LwDCqV+3vgL97JyR5Cbv9ZplmUehb+spLZawzXBy4avJKebo\nHkDRVhalhNRcHorwZdJY+GmY+7LgvBMY+qFKrh+X++wJXpeTTRvY9AZOzYFt\n0LjePiG6Qa8LQdzv4J8bYJDQ1cDSrcdXt5V2fIoUBG2VKHaRu3L8tzMrvO4I\nHhSxOO1ICO6w84qYQJi6E2/f4c8B+pYo5ScMgdorgnY1DCPFtYQVgTB4rXjh\n47AhebEzHwJJC5a0nVOhiKGjhRBoUTmFjsZvwaBDzIHvTSYce8FQEROzBDOZ\nJEs6lBFNRpwapmo3ltYYs/1/JW/VtsD9hT/rMnJ8Dibs4fT3dAxMExKpr2GN\nJfz0fwowPx1yqAkwDE2kUdnaB+UuDdyRIjWjqkH2ktOCBDI38k2HOlpkPKxN\nvGpY\r\n=b7EN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG0LJGPsvx2jZB9w9aEjR8AiLlxoGaGr6GZF164BoT8EAiEAvTg0KY043uM/BT83gvTAvgLdEX+drwFT+DFRDwXfQCY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.40-alpha.3-objecttype_1544409286436_0.19525877540117165"},"_hasShrinkwrap":false},"0.12.40-alpha.4":{"name":"teambition-sdk","version":"0.12.40-alpha.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.40-alpha.4","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-qA1ptGh/jC996VhMF9YYEmR0ksTo1c/wx3zB3GJi12OXs0oB5X44PAK6X4Q24I8Nb7t6Jlk8AKfh8fD1zHc6jQ==","shasum":"1fcfa6e47ee37b3339d45125580d748e25d08a24","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.40-alpha.4.tgz","fileCount":404,"unpackedSize":851937,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcDeJlCRA9TVsSAnZWagAAsbYP+QFERpxFi8S8Ix2K1FYT\nxonaJsBvxOxvcz1dcLW0WYPn07XRsytyOw2OMrom88GkPg/+/wne8G0FIRq1\nRFJDJ9sQ3B9AMS6foIEaIdxB0lK9NR61Q06xJz5dVNO9YS+vhyXugSKmgKPg\nSd6nNKzm7PHXX3ZxAoD6nflOYpxtzdBym7lHl2ZYHjcy19MrlznJiQRvWfkx\nEdoSVbu7ACpowJmkrCZLPFn8kP5db0EKC1esGjvh/HxMshCEcS2phrpaoeOP\ntq9Kd3mFhH6oG+vR2X6NteJGK6ZI5YGtXHRxQHeDgcAZpWtmXiUiEjL4bNui\niCql3bvESN35mRprKsCM0n4HRqZFay6oQKL6tr7oSxmgFkIuqV+nbzkhZup+\nulKIdOmrGUG9lFLEWiHAriBo88wWJ/qRh6TxpJdzJ+AwRYCS1pnnL2SsxtgW\non1XY9GunaohsAKjtHRJUvKTkIsDG6gCKpDKNbIUeDwO6v9JWOWQ7/7/BTHf\nU/2RVmkfLO7BLCQ7l+ymEuAnejKAfo3jPqPAIt9F1bYuWxZr1cTO9k9qh+XP\nIFpnSIjXaZdxMNgA5B15zgxdCljAh8e0+xK0lHTvVP+PXrTYJBdnlQQsSDqE\nRpPA7s5uLG9Kpt1XOZqCBBZyQ9W+iNVgK8p9hyZeyPnKX0gg39d1j3PGrHyS\nLxrU\r\n=hEIm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCKXycDFj2XPI8K+vOn5wKxmT4G/05A7AbXlImnzlzZBQIgYmXdCOqODxJ7mJ1htetJAN00H61efx7KpJ6Wwo1Kulc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.40-alpha.4_1544413797188_0.29556221405978156"},"_hasShrinkwrap":false},"0.12.38-patch.0-tasklistvis":{"name":"teambition-sdk","version":"0.12.38-patch.0-tasklistvis","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.38-patch.0-tasklistvis","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-d8bUQQdO9Lyk9drvY8Lz/m2IPkvjj+bKiPX3dOcMxLqyucMJClpbsQJTOdQwP0oey5gTc2RK1pXN58OoCcWhlA==","shasum":"9cfd0ca3c1edc8a9c081d91edf4984585de1f2f9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.38-patch.0-tasklistvis.tgz","fileCount":395,"unpackedSize":832839,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcD1CHCRA9TVsSAnZWagAAWr0P/3QKfI2WC0E0UX9UKQ+m\nF+OKJtsrEq7HhJkUCc7R/DwWTbJJowxDx1F2oL8YvNp8YanImuSZzZ65dJG5\nz49uGWGT4e1lyrdiCKMJqFCzOnaPYF3O3qV5Yh4j2crssmlwGOsqfs+9uFPT\nkWbPwninn5VEsGQIp2+IoG+wfBUeOxiqY5f5XsK2k2dbiz4cuQBxEjNhK/LV\nn2ob804YXfSvm6FejNqeLtXSUQ/8wS3bnUYH7m76Sp8r74OrD9J7wUBwtvWI\n+ODEwATn+X3nR/jXD/ZeHS+CAk5RTtYWWzVBqSEfkJhK2oUkgUjbxZUNZNyb\nhSc3TQpD+WYoswFJmZZnot+wiVL/MMysDqKqznaRuf7ZIqdIXHN4Kw9tISup\nv3ldMxQmOTqlE0wBRZG9qd09crAVKrlir511S8tUBK6sOTRuKlotFIIhgl1k\nqJ/Xe3anUk7Pf7bX30xKJm6UAbkbumQ6D4OyLYJtsl2KhA++XQPRP495dBYt\nIi+/uL8DY+55AaKgZM+87tl6g54m/odsdWNUkCDrErNeW56JMUpxzkJ1X4Cm\nm6k89TwDOpEGqD2638c/kN4uGYaF2exmZgLT5Bsb7VUNlP2HjvJtSS9PepjO\nxh4cItbDX+Xg3hoU+m7AxgQSvliuDyNf42PnnlDR2LE6mZuTV9FbNTY1hKZO\n6U6N\r\n=6zA9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFmBCGRhocf+bpp5nPpFosgdDHtB8CQKzubBaJ5E5r/fAiEA2/akBpZ7yk8gpNL1GsAy5MTzg+jlf8OiEH0WVKfvrYY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.38-patch.0-tasklistvis_1544507526945_0.1954631211582447"},"_hasShrinkwrap":false},"0.12.40-alpha.4-testplan":{"name":"teambition-sdk","version":"0.12.40-alpha.4-testplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.40-alpha.4-testplan","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"nekolabs","email":"ratsunny@gmail.com"},"dist":{"integrity":"sha512-CF0baY+pdGlEE0+q20pNMIKl+SMtlHUq4gLJH7RgSc1DcayZuIHXmyPqt/5ZNkUNkmPekq6zh56B9hHd1wP/QQ==","shasum":"afab9a36e79dfe1aa78a9699a9a8680c84ada09f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.40-alpha.4-testplan.tgz","fileCount":404,"unpackedSize":840216,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcE2n8CRA9TVsSAnZWagAAvggP/0OlJ6XqT6GJ5aNcIyjL\nbQ9+Y1Eh7qNTb8v+33CAFp4qHc++YdM39pDDCyggWHFpRQL8dfVbJrNv5aWS\nhuT6QVj/ptAEpCEfPMZcjLXWzHGg2tLtXtC9zG2FOTydcgH8qH25drG3mZOa\n/PYP2q/rzwiF2Kl/ropuvdglq2+WlSzSqF8HaVz+uUPek+17rThvR7QoC13/\nnYxcEs4OoXrw93BqYD93ElGf9EMQthOFRaDHVAr2W5jYwUupzMBSA41nRSLq\nRq2hum3ihhduNJwzES2WrVZuGcflB5ErGTud8EJ2dJdXw5x9w43nSNWduI1x\nJLZ7xNY0JA2obyazJchhT/izLMN9El1twDoQltJen82rK8MzbxQbxo+XC5MP\nLHroKfHoL7duD67h+61Fae+/0MjErtYZVQuYR8pOCX5p2YwkOZ9aWaBFN96Z\nPBQswka4MW9ckdMZMXlxX4ImJEtXn/f8Lmgl0l/tYNoVQY40vrANlMpIq2CH\n7DV05cx3BogwRw2nCK534Fhdb8KNUcxoA8gp8wXefAUYRcxeeE4S/vbYpXeE\nv/Kq1XFjFNWt9SKkXFldCwROrXqc9kDI6wDM+j39MvJBOl3xOJ/SGB00+fNs\n2EVWGtfOD7bwYw64eXvBJVgiMX1LaTNQV+vN8Etl/Ma8j7koITFtbE88/cHj\nmGDW\r\n=gdh+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC42ylMFXsqwn+bYCRluPjW61/Ain7zLuxaTcVNfiSerQIgX9Zg01L46cYe6A1t72fNKo/NJ1u8tsKjbUhVPnPFm3k="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.40-alpha.4-testplan_1544776187903_0.4711989658497888"},"_hasShrinkwrap":false},"0.12.40-alpha.5-smartgroup":{"name":"teambition-sdk","version":"0.12.40-alpha.5-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.40-alpha.5-smartgroup","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-+6L5X0wLJbt3Mf2XwOtZPRlVr1awhdDIQVwvslSuEwAcA9N2xB02zm6bPYr9/wqlHwsKlYtRLkpwnuSas75Hmg==","shasum":"90d49e3aef6be392acce0628487ce2daf7c0d99f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.40-alpha.5-smartgroup.tgz","fileCount":404,"unpackedSize":841492,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcFwVhCRA9TVsSAnZWagAAjGsP/2/qBvFkr/lRmuP1rXVa\nzS4xVL+aNRaVFD9RTQp8nTkyGJ9RCgGrq8mckuM3HSEV0qUiUU/hL+jhx7yU\nOFpQn+W7eJ9qh4Zv8OU80oeJ06X0Q/TLsR1cRRUEVFIkIKwEkBRu15cyourq\nzkWEKV5iCEIYBkZTdY9eA+9cv18IdqvkvNTMwsO0xCie7f7bdqZxgopkQ7DO\nX/qubbm5IGIDwrmdKo3D6B1773b73u/SnNtBl814P7ij9dNEidZHGhbHBzbe\naNHyuJPXm5LNF5gICX6e9cJY+EiRjxmjcH/HHahxniIid7c8TBD8aE/+yDrV\nKsaPwzJF0BuaGidPf6YWyQRbsLiXaoKsOLbfrVJbu3w3Grn6VQIVNg5HZTt+\nB/YZAKwwEwW3kZ8omwrP91mp3nOMe3WMPw+FvtBObjtKYXx66pnfh9Sm7YUT\nxW4rsTjKBKcaq6vxkS+E4brihqSgiAqYagdN1SFjejOwkAmDyFpTj+2CQpDG\nXqg4/k/NeHVzI3kyam9O1qgoC0HSuOAwO7b85JaQM6FMNYkknQ/JUD8okLF1\nSEKv4PEIokzKq03Xsy1QUGxuVO/Z8lRvslf+n+Mc/tsNGHSTOQ1JzIiH3pQS\nC50Wg7MJ+uLooXcpIlZnb+vSZdnO9ZS7OskpLPovlmBsxcjMr6ASteGmkXQM\n6yYQ\r\n=GSq2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDpFRKHjjSijovhZhEF4WvCXURH7jbwddz5tu1LlQsQNwIhANZNNQHHo4Fj9nCGhDdx15c+5x4BK73D9zxt80mO1W3G"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.40-alpha.5-smartgroup_1545012576722_0.8502413433133738"},"_hasShrinkwrap":false},"0.12.40":{"name":"teambition-sdk","version":"0.12.40","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.40","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-Ru3GOk5SRcbRW61mvYWZwu43owoLuDIg5PR76VuH8Ak8DatK/P4RVt0R6n0VrFI8f1HdRKk3MnvW0hwI8vwOmQ==","shasum":"270fee0438a5a4faba815b9fe9a51dd6e3c83573","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.40.tgz","fileCount":404,"unpackedSize":840169,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcFw87CRA9TVsSAnZWagAA6F8P/2H+TQTMUQ4k828+J6ap\nP7lUqQgSn12zjv/OwL+iAfBDooZsc52mFGQFWqY93i5yNOGCRBwkPkVZsNeg\nYIDxTLi8wXe866dT0qfqoEwr0/32ny6ZWlZeQNGhx/VXCSYupminFmCAEVcl\nZeoIuspA1FMS20CI5wXKNKHZ1Vl3YVfagHjDX47SEkQcKY0SnHrCcZrURURy\nIVSnDoVZMxnOUWQhpnbR0BikIiTItJIE/8nwh2HE725v12n5zOVq1D5bej5Z\nsZEp4qlXe8QldbYsZIOL/RUrOUzzlymWJi0rv2KIBfYYYnq6Qt8D7etJv/oY\n7nFIlR4Lr6sEmPboiZw4o/BCWnBJBgFqGU3/sRUK0d3SN4uU4eKU7igoMS8m\nrhV3IecRDRdnMTpmj2JSmTi3JGO+VOuRFsMslP8vvw/SkAPRB7c4mbt/eWo/\nqPpdZMgfAciz529VrrQERBEXu3hE97cUJ7W8zPuFeeBJkBmJgDncpVqADP+0\nuLdRfoOlZ1nN4jCgVFg7OWDo+vtFv9RF0BHbGIEKQNoH7v9sP1vJEQLlCnSu\n1XtvGWPBQ64xynk3OPBG8+hmI4jRFeRFSc9Mn+gsknUAZw5xMMVBaqSko57f\npjj27T9R2+4pV5xcgs57P/J33BQ+KgaZl+cB0qmiFx6zDdJmmUF3Me0QmzkO\nfkkd\r\n=KjE8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEqWgfSsM1mDmMJNrx2sJ00bDyH8afLp1x2lRUCcOuj8AiBDU4q0MGHKzoJjHbrPUA6wTQVHI/afsRDiyjVM/flcKg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.40_1545015099363_0.8134755267798779"},"_hasShrinkwrap":false},"0.12.41-alpha.0-smartgroup":{"name":"teambition-sdk","version":"0.12.41-alpha.0-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.41-alpha.0-smartgroup","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-GneR4Kwb/grqAVp89KxbdL3K0wWGwBl89ew/MY+4Nf8Nm0VHxrO2akB+bg9gqQFD1SMfk4Q5mpEVjQeXi09rCw==","shasum":"c6b0a170625d204c8efdae0c6901b6e7f6f0263d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.41-alpha.0-smartgroup.tgz","fileCount":404,"unpackedSize":853972,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcFxaGCRA9TVsSAnZWagAAVFMQAIjtTq8M133ciuFfMSO/\nw4ac0ublT9brUqs54G573FgMjcHJVZrLN/yBMeCGzvX0YWKbXgsggwALJ2Rz\nRfT6IpavCntuUR1eRfd0p3bxT5WrJZQ2OI3t1EJOvGZFzBXqOYv4fOyEWfH0\n3XClGXHC2SaL/xk4l6GRufHJtucdNnutLZXZsADvMPmROnP/CyJLNNaq6RjD\n9oHnLoAOmmpufRrp0W1BQano+ldc6KPjnW5fDyvvOMjKcVBomyL61+iAmlHT\nySzV7hhNNQj6u+7uWyMbBjOBZPjS+yZFt/PGM3oLSSUa8m6qe1zQ3mGe4OvU\nMF/NumKZ0Czu6aJrzOaQAY9gW643EOjWwy/3Z93P0Hqx0n/+xPRND8eaqgHV\nbsUGnCHcQ64HhxgIVxszoTL1vyC+iki/PbHqy9cGkbfKqhIwXFmWxPvQp2WA\nf3WdNUF+L1cNsbVeBAZ5eF6qcs/+mfe7I7wNufQGxAs/i/gdLSlVZbK96wQo\nIgwCAf724LtPHXo2HqLjP5SiFG7Dj4BvXalNe/6wk72/TdD0onpvPIi04fnC\npTNkUy1PP8f7FfTo8eZSMrTVXyQAfMJ0fm43oPshu838qLsL8irCbxtaeBGk\nEE4/hC2U2sl/jmrryVkryoJ55rRwv54BSaAr7CEI4GroLW3D6HXNgTqOEgJh\neiNP\r\n=vZtE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBR5pfQcUsY+Ofek8U5grIWINpgyL25fQZl7h38l+0RJAiAQYf71szkO+z3KItOikoEDD7wmGjo6uM1V+FLtmBnu1w=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.41-alpha.0-smartgroup_1545016965438_0.36789783040956325"},"_hasShrinkwrap":false},"0.12.41-alpha.1-testplan":{"name":"teambition-sdk","version":"0.12.41-alpha.1-testplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.41-alpha.1-testplan","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"nekolabs","email":"ratsunny@gmail.com"},"dist":{"integrity":"sha512-3YN1W0qzaEMlCZICoBwne3SfZ6C36zjGx218ER3jPHUE21Bi2iVT5x3fcoXmLgySoiQgPPJDsBcYkVOYc4OHsA==","shasum":"ed8d6db2284d8021563f828d6561715e9908adc9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.41-alpha.1-testplan.tgz","fileCount":404,"unpackedSize":840552,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcGJa3CRA9TVsSAnZWagAAT+wQAJ6y8yQRWk7YfhHXQw47\nftwLa+TGd5qjou997rLyAFhsmcV8YQFsIuYIpJAvtYXHuqE2xabQ5I6g6x0B\ndecOzsnuE8fsBTJA4OOdxCudIk4ApzEfimQI+hTazVAc8jk0CXOpMG/hOr6O\nDqyB97ux3u/thlcv/Cq1j5sory7XtSJk/mwe1N2SE4UFw+LD5OFGKK0u4ICZ\nvcYfXFjyVTleuZKjPke/Oi1yy+7vLFfLbnjMzgch5bwdmNbPoFJdQ62a+v7L\nPnk0qR/KhVFzSXcHCqOgcaz5pToBwI1Fp/pWmQVw2bu+spmYlKORm2s8CGHb\no+x5WDuwP6wm52iMgF3D8mJGUtEnLm7bk+groxEfBvJEn8PdaNeLGr8wr7PM\nLID50wBL51TKV4h3PbG4zPXzmVBi/JT2npCKHi5dIN67qDeXSw6AuyBQh6WX\nTNJOqvXrmEcztJ4MVtxHZvuKHPJh6glUfUNd+0aFPXe6hhLpIMQSIhjYSKQ1\nWJHA4ubT2ECpF0p5TnWLt3vSf4SxN0hCgsavwVNv0SL+X7YyZd6ZlA2Aj0kQ\nvAbg9mPzlWu0dZZ4TZO6heT3NV5PydhARJ2rrBvl8uZlSsw+VTfYiGySzCtF\nEOuuUJMhl5B11Q25P5WBNg+FwV+PtRNv1Izys0K4/+zFjjBOpX7gjGORNKQC\ndC3W\r\n=/wyG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGnjJ8l1209oWoFXp9rpwcM9k/R0dmYAxFaNmXuug+muAiBncVWf9urWR3Kwa1ohz5TXZGYwCN8eVmwYkjF86qwoWA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.41-alpha.1-testplan_1545115318701_0.08452541885881715"},"_hasShrinkwrap":false},"0.12.41-alpha.2-testplan":{"name":"teambition-sdk","version":"0.12.41-alpha.2-testplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.41-alpha.2-testplan","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-dkfPu+1+NA1be6SWXgF6CIEZieqPvhwug3ccTwsiTuKGiMH41PgTH1iuUTO/jmVuMWNcDyh05iVd9+8NlcftPg==","shasum":"d0d44877b7b927216c51adc4468bed446749dda8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.41-alpha.2-testplan.tgz","fileCount":404,"unpackedSize":840705,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcGLYfCRA9TVsSAnZWagAAjMIP/3xJaXkK72c4vohxXBj0\n83nyHE9HZQZaT0lRuxhjsJRIefn7VthbyDYvkMAAPiF86Hecik2GJTFQH1Tr\neXIbQcoZkfrjhINMGU0tDXqhOQ2QiLh9AMEQKQZ59+gvbJZWMVMNooRxFm6c\nYX3ETX5PJana7Gl4fymOr9qhANzKWt77fjcz2PUwBg3rvxeh3ZqXhpBlyqgr\nTaQUc3hEQ2+cCbhVDlwqtM7a5LKH/a7x+1pAyC8MV2IrWs2dd8+TxrLQ9gSC\nPPF1l/NINwJFpDFv+Yvxc+YYTVQgs5blMimKUUJ98NlBnuhyA1MdyVDHzNc2\n2csXOMbHXy3t794SIp5qM2VOEe471fwdwRtAeLqbHNDO5lBNUGcBc1PhFRQW\neHP/Eptgc97kL1FIdba2zWxIkPVqz1fkJDQ1uflosB/fs4BPFbh9IQ6rHa5I\nlMdJGrhoC/uYxYdfQf3xHsbfLcdb9DRQyD77a7UvVvq/snEYMUBYDXoY6v6r\nBpTfePyVvK3A4RFmwHcqDv3M/oAyzH+TRqUgNmrxKedK3PzQLLk9580v5XZQ\nqD8BMds2mt+RvQoo6pvzHS/n1HGVoiKsxnTNoMm5Z0cYXVfwneeLQyRntFMt\nKL1eAibGtxvViupEQIt2TcctakNe/H0E8fikG/DYBso+hGJv7/6aNtRXb0By\nfxY+\r\n=mU/U\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDeQFe+025Irs0jKknK5f66WVuP+rXeowzDSaAM5WW/YwIhAObAm6YAL0GlvwGTLi7sRQ6OFNHnPKg8kwaXcrob0rmq"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.41-alpha.2-testplan_1545123358413_0.38087019155639146"},"_hasShrinkwrap":false},"0.12.41-alpha.3-smartgroup":{"name":"teambition-sdk","version":"0.12.41-alpha.3-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.41-alpha.3-smartgroup","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-S+8Ay6dQKQNe8XJe3Bhe7VrCasF4HGPSfj7TwhO5j8bLmXr5BnJyjOdqtQQYp9Q6h1rn86qvUhTMs1CG383b+A==","shasum":"fe6f7edac4cebb5afc2859504979bdca5fd9c845","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.41-alpha.3-smartgroup.tgz","fileCount":404,"unpackedSize":855352,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcGhOXCRA9TVsSAnZWagAAgrIQAJrznTHyH0dCS9F9qWoK\nucmUJKM6NLHGiXs0ny4CHmaY0k7NL2NMqLNjLEFf/H/H0Lroltk3ZoAMmw1/\nLJbuILcqpaYDAZxj0zz+RZXuQKux9grKji20MFzoMgPxQyE9HrPNkv28Wf5x\nO86MqZwOIBuB25UkOfz8T7Uozxo9txgRa6aAyGWxzr9Nk/YXfrd6VoK8yYEO\nPwafj87rCAmY9jNZ/w9ToBiHBznO5m/yI3hekrhLoIUyqNJa/d0sshlOHd0q\nC6rZOyDt4mjcTqLBs/F909caoexxmRMbuiMzadMIKd3+Jx4WRovAFGZwEcfA\nnSZpw0uZ3o8owc+zcEh+YJG5yNJ4vBwan50m/e1/ineuky6wMl/m7supuw+m\n7hzZq1kALaQ3HUM6sJtymx8fDon1DlF40M+0JJ5gyQLANUamjc6Gg/0f0VV6\n8vQqrWhzTCMh9KNAMYk0Gu9koR/g3ApcekCiyK/UOS5lKOR9IM+UGbLdy75H\nxEDDYh158Vtbc/lGt1/czseeDnH5SExoJBWOi5llcxmpBghpPrBtAkpQ92fr\n4ZBklBj9W+16713z5w5spDrTv9nZ/WYTll8XSjly3/XLRcc6EhOiDr6G6wK3\no4q//+sB/vCgfuApPTVFAjJGCpPlQDqcc+plZ/xYdvhzQWxLU+ky0FcMMqdj\nA39l\r\n=Dopd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDpZ3DK1irH4HC56jX/4shBa1PVlwuMx1rt8BIDZXCoMQIgCEhkCKfxunCG7wz0wNf92dYHmllZLN1eJP5aCX2AlB8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.41-alpha.3-smartgroup_1545212822979_0.7857302268039523"},"_hasShrinkwrap":false},"0.12.41-alpha.4-projcluster":{"name":"teambition-sdk","version":"0.12.41-alpha.4-projcluster","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.41-alpha.4-projcluster","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-kV66NsSVQNLochfUh0MkDMGZPHiiGsxyzTXA5IArnhahlKYWFQJ2k1Cgxmct567wMnBkYKPW3TpLeZsMH4NJqQ==","shasum":"4c6aa3c8bcbe52488aa3250c2a3f014a55954d96","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.41-alpha.4-projcluster.tgz","fileCount":404,"unpackedSize":840209,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcGhx4CRA9TVsSAnZWagAAnuAQAKLF6664IAb2p7VZQ2rF\nfbpMfLoJvd8yiWsBYgY2thnl9xYGeZHFdODbFL+8tLgJ6eWpj+hWf19g6B4J\naVk5jO6x6Hb/vRwwO8f+7G5ns7AZJZi4s2IICUaqTSQVzt3Sm1tsW2u8ibiI\nNUSATyrmhH8wdcMxO81QuGdhjm1Nk0rwECTk84kqoqKMVu9yZP4DU/kjs8Uz\n6/sDzPj9VOh8PuCN6IF7YgTJD2RseZuKr6VL1BgRPO3HlKTKkQ96Ii1UtiKb\nqBVd2cJdEm4MxYVt6zMlPFYtba9Nzhl3PjD0G83FPJoh6gWuvoNn2KxALJBp\nBo5F8ztJz4FPGZoLW3YfIrolsBHaAgDsjZKu4O33j8QocswxnA/uqYb2+zVN\nltU+y29eAQuXSAUlHH125puReHHF/8hQQZWKeaDJ0mcMplp7aWzkaGL/2TN3\nmp/RrBcjf21kJa3/nqnlJ3mY8P8sxB1IW3L8vJsBgu+7RwEI+h404DgH4v1m\n/CCr67xCxSNjv5RgDaXXv/QpFKXYDQij4sNCqadmVv7WFWNENEks5QWyV3Rf\nBr8YdrnjSbDUDjdG00uDIX5uc2q/ap5xCpqBpYoUfsBYEnZ21aXazp0Hddhz\nC2sxteeLHxTkpnxNzpdiP0xt6YSe5WG5CvLIgHTs45JYAfLjnw6BAUI6Oxsk\nw+V5\r\n=XLDd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCQhL7Yj83ozkueiTUL//78oYrj3hiWeLSCT1FVjV/5JwIgc8DA+HhEpaXEhjdYpYE4maXSZxvO4jO8rFreLkCfliQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.41-alpha.4-projcluster_1545215095393_0.4962987489176893"},"_hasShrinkwrap":false},"0.12.41-alpha.5-flowboard":{"name":"teambition-sdk","version":"0.12.41-alpha.5-flowboard","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.41-alpha.5-flowboard","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ZOxzZWO4yHQTDkh7TajoXsUhPb1zvmePrwQU2MfTarLqb9cdBsKcSpHOwQ+1TMm/QbyZS+qbyt/3w3oyU4qW5A==","shasum":"18488e7ef463f9777faa89a9aaaa9671850e2ebd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.41-alpha.5-flowboard.tgz","fileCount":404,"unpackedSize":852438,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcGyt9CRA9TVsSAnZWagAATf4P+wWPONjOuu59XFhleexy\nlYS4g04UmJwk4GJ2G6SZxbdjxkZHP/3pNIv7xub8cCFpvDSjeaYokvtHt0ck\nQzY5r7EOC890kTCfSH4VfSpcFPLGACqibh1GCmMrk7ROFYLb8c+SVYadbNt4\n77LvkxPEf2bNgoBDmAKAZdDzdqxfrR8skMABDYWy6N9KjD7bsAfAmj/+/kSJ\nPyPyHfmBluIarqX90f/abi5arB7UL4SiQ1tbT8ttQo+QPyn7Bk63ByUUczjN\nVbbfeuOCa3n6oo3YyUVGILTFzDYrsQ97b/FOiqqVb58e1I6nQdYw0vIQz0jY\nKVXrSTKttwaAP7lnYTG92VJb/TsaWmSEbKTyXiackylx0dp4DSkqF0q4sw01\nWjuBz9vQb8bngZiub01V7UilhS0kQ4jt+9kfFxAWmOKaSjTBCMmHyYKlSvXo\nsB1skicH7JvbLlKkGVblDoMSGoMIiyc+ZwN3kTyG6JqnTRysp/fCvnbqwAb1\nli9Cu43ZvaXU8gS/wYGMSwEgYT0XHVXKxcFDvKUVDIkMlX1AImNxj2mF2m+V\nSV0z2xcU1Iy7ZZIqeHH8+CEucml60TDRgpRUR5qs4mxWnkrkhIrz1S62yn3/\nvlkK+asq9CKAPaqkN7ofi8ezynBx/2GRSiqYzAu7DT2jlMdEClZdZW0o99a7\no7K5\r\n=jcUr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDi/2ACH0IiE9qMkBgDbcN2QIbc3qbWjVPy+ZLXkYOipQIgW87Qg1TWpHkwcHUwrmQfZb36NWRgVWOcrutsItxAzfM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.41-alpha.5-flowboard_1545284477268_0.7308805124218871"},"_hasShrinkwrap":false},"0.12.41-alpha.4-smartgroup":{"name":"teambition-sdk","version":"0.12.41-alpha.4-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.41-alpha.4-smartgroup","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"nekolabs","email":"ratsunny@gmail.com"},"dist":{"integrity":"sha512-cXVz0j2tJ2uFVYWE1vzdCSahCM23ljVkoeqzBDiiQsFfS17vjLZt3qzXoysB4buO+l66SUMl/ljhaimvBS9RJg==","shasum":"cdb067c6d4c35dd577d1c2ac297e95934b76ce2b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.41-alpha.4-smartgroup.tgz","fileCount":404,"unpackedSize":841492,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcG53FCRA9TVsSAnZWagAAOAMP/1LxKwDCuB2AHTKFTxPS\nvQh1QYlT61CHOgzs8zN26yi2borGJwzW1+3UMMxjI6Yf5bYlJYYEmftTW1uA\nmuTwVJ353IV5G/WzsJ8lRZsl00nEWZ3NtuCgyO76vL2aMIZglhvIJD6+AqFu\ny2yxFcKQskPolSiBw+eXFhZ7pb9tsTgz8fgbaA86/c+np6i+VrvpmDkwp81G\nn7D2g7IAseP0L77ZcMbZD79ukiybc5o7Q3rEAJJgvzw4guMTwUK7sVtP35iq\n3BG+21yaVnpQerfPdsLAmd/fDa9PGW+Z34vPV/Xbg0E+nBo42rA/7cIE7sSJ\nMKcYCwg2D6rWaFEnkOZjdFQDZ6Ygj+yhxQjyjwc349GM75VmzsZ2I7bhSISn\nqWL4yAHL72EadQYVMmVbPD/2VlzRQkXcIj/UVAa918PuujwECEqyTigEV4D9\n0DWPxy3k1kBt5NeUJnmvs14nfaP8nTbShmjX9hn0D2t4TIF+3OjHi6RRu79u\natKmwljO2kljFb9CAL0HfOY12y+uUkIG1LY1J3RnDuOimMwHqmKVog5cpEo8\n0H7ZtqJMS5UmZHaHhau+39qzYAqSK4XsJqt3xVsXgekZJEpIDs5Q1rZPEBel\n5SdFBSR00hKef/SbHhwk7c+LD0E7EFPwBufFx7JMKlYsEbN7mO5/iAmTzTwC\nYIpI\r\n=cIRf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDnPjkJHDg/53e+a+466DpesEbh1v7vVidJg7v5nG7NkgIhAO2eaURoWJTi5h+ukuKTbHEkLyEIEKQrnvmN3ule31OL"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.41-alpha.4-smartgroup_1545313732651_0.9957003878813653"},"_hasShrinkwrap":false},"0.12.41-alpha.6-smartgroup":{"name":"teambition-sdk","version":"0.12.41-alpha.6-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.41-alpha.6-smartgroup","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"nekolabs","email":"ratsunny@gmail.com"},"dist":{"integrity":"sha512-l5wNhmybY0VRVoc/L8kTP6qtAya744uevfUPWnq9F7qg4I1dtrnKuFNHm0cM7784Fjlw0deAyrLRXR41tvl75g==","shasum":"e6f95b993c19a11bbb8fcc672b8608d34f69ac38","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.41-alpha.6-smartgroup.tgz","fileCount":404,"unpackedSize":843101,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcG6BgCRA9TVsSAnZWagAA1jMQAI+InP65kqphf4+5nQNA\nEZ7bWUk62lMuDl2tAtbc0ND3aK7hCl3KH621qbwMz4m8QQmNZHNZ1d3IigPV\ndW88ImjhjLShOAWabOUld4J8OLZWeOEM73e5WhxBW0Klus0Bm3Nwn1N3ej9/\nHqugWgVoL4IZhEtJRmPHJeHStlATpuZKUKmodSsmfo88xLSrPFgLTLDxG6pl\n6APnlTU4MGV4LWly5ShjUGA/vBtmuS/dObkL5+dbeSqQ5vgWnsC1R1z4V10q\ncgTAh3MVmDwvmjy93CUlDBGjriE97aV8Es5YuK3Tc8roRATId4mYPCmyuQm8\n0k14WnfogwsdPwUA4TezFzWfHaPFSY5x5Cviic52cd5wbxI/U4bRta8s1jns\nOioDmHSib+SsoFI6Cgv6LE+0/Lh2MZr0E3AUZRDwnJo/uIq1Y9+4KclE8lPh\nnrR6iV2GuOnWGZNlCH4evWHAg2YoqRYonUQ0zi1RCFHxAI/lhkUMTCehrUgH\nlFMk7e07/yoX2ZhO512K4F2Lup5hSukkYJBwyaYOkFmdr275Xblks5juhnWi\njshMY5MZ0usc1qgC8bWXep/BGmAOY7gSY89lPMOL+GWwCDm9YdbyMglSFB5c\nn3cAUZ+gYPacw50k9TV6PwqwqJTyXBYydgwJPlUTHOus1d+x4/kvuV1Ru6QR\nkLHS\r\n=KhGW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDCqz0iD6ima64Nz4Mck3R+QeYV6oZLKWVJpDFSHQGspwIgTjMcT3XjTUJ6LH0ACLQuiTWPr3rlP1bgeAnoe6YGy7s="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.41-alpha.6-smartgroup_1545314399774_0.033727015445933484"},"_hasShrinkwrap":false},"0.12.41-alpha.7-smartgroup":{"name":"teambition-sdk","version":"0.12.41-alpha.7-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.41-alpha.7-smartgroup","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-94K68zH2ft0xJkkqoKFaTkUZvNG/GDng9E4UbbOTDNCX0C7NRS5befoayIUw0fXb5zjV9i3bLB/8k1PH6gqCwg==","shasum":"77be81277b4ec33ee7b7d73aab128ecec761cb4f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.41-alpha.7-smartgroup.tgz","fileCount":404,"unpackedSize":855352,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcHFiiCRA9TVsSAnZWagAADRYQAJt4At6XAvK/sDBPOexp\nlDXrp1gat6r3TsZS4+6HOZcvRTITJ67m7RC1uZh6Iyeu62I7OPKOpkXkw0j5\nVYbAtHyicN/+OKhHabfVTTvctsUP0F3mrTJ5BzAAZDbyN3nHHbjTApWXHXQo\n5JltTEzhy6mXeJGwzjFK/GZS0yJWW/WEANsN1PuGULePQCPXE/3W8yo8g7Ou\nJOKTxHhopALmFNBLpIicf5Soy/MCFtoj1Z6kYOgTGVMAtPKUEiWcJd/KIekz\nUR2/tH+3NgYjLnwV7643LJTe7D6t0V2fq8MBCzAj1kIg2mp86eFL3W8fMjnK\nLL300gISmrQVJB8k/N7ch79x6nTnIdoEfF4cVOYjL+KFn7yhF9zYitQlD9AL\nGVliqtXTrFyHXzGUJwLXdXT7Tof3qHiIJz36UVr1Fp9cIx9zUebaT7/3k8A5\nWCJ968dAcAg+3EXr4Mv9k1LblxazqERHak7u5txa+eaZ+ljVtQDmB8TCJNQa\n6yB7EzeMHdRwQ9QLOwOpUPjvJABwRhoBXNATaIlKrhTITwhOfhqaZAoL0UgH\nRRpb7xoERPrpO1+jUOZI0O2YgXtR17R8yo90GCws25be9vfN2tsOqjtPNjV0\nnoMOsELg4yDRsQgiJR0gX1ikQnVIAb3WfDkon8NaVu4ZbsoeAKuBLuReVdc2\nHl17\r\n=pjTC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB4RpuANCOz+cscHiEf7LkbDTj6RWDzeTwdguF+0uF6DAiBPRlBVr/pCPB5MrSOmb4zxw3sjbWuu0TkugdwJHiXvPw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.41-alpha.7-smartgroup_1545361569367_0.7085621547543572"},"_hasShrinkwrap":false},"0.12.41-alpha.8-tapestry":{"name":"teambition-sdk","version":"0.12.41-alpha.8-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.41-alpha.8-tapestry","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ClWSMksr9jRxwq5daMJYKnAcb5XDIB4DyKW/RZYt/Ho+bc4HdxUEEWQgVagQuL6ZfuMIyPFxQ0+NhY1BhO8oxQ==","shasum":"90dab036d1c1927f8203aef01c516594a10fb5dd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.41-alpha.8-tapestry.tgz","fileCount":404,"unpackedSize":834496,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcIxLjCRA9TVsSAnZWagAAkJ8P/iUL9qIEjKKxRWF8hsz6\nqJfnWM4nYv4NK8MLIK4mSC0+zxlTUcNonrNtWzmRUdOB6jqaWEhu8Pyy5z5c\nfT+ctypP2fdIKQOyD2YoSwGTKfMvG/VH9dyGhma1pzbJMSRcpofqNwBnAhkj\nJpKpKECRqQnJ1iEFsT8kpP6kuIdHrKYaE1f3vQY+AqjIpLmp844MmWC8FJsi\nbIMoCsOX/1hj4CpE3JYugOhpS14lK3TWHnD6dj7JTbrd6YyTP+0f8bLukWfG\nvqpUd11/Y9mRaFdhorPfCOJCTrT3F9k1kqPK20GQRO8PeOVRaxGVsu76F4tP\nLJySGXS++A1E69YPyq/6YtR9QbxfMQWfwxqxr/BAD4vcYEEtyCGlMjsU0Lxi\ne/Fs5jFX+H0wpn3OOdgRLk5UJtwu4dSYAeK4W5qVIKI89XVsZiDzyxWK1YI8\nbyJcxrJfpwwex/b99CI53KnUf3tYjRRs03mwG8rIRlk7ysUpy+VRB7Bok1Rs\ncppAVr79MC1umlQfant7i8zd2fOgx0Vd7i/wZCw0u+d1e/HlV7mW5y6KtM6c\nz8hXkIukEbjS/85B9uZa5Q26XxzVioQcjeCJ8yy4VIxdQeiZbKdFCW3YsibA\nJ9dDmPJea1csSxo7MChCWhhEfTRYA88S/jrtiBf6NKRdk29kybAA19QrPveh\nIoUR\r\n=PZ2V\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCN29DCwWnTOtfWyj8ylQ7hV/lJMoOewilbU/JS7UnIDwIgc/d0Gk4QNF+TszriOGB7OPz9f8fWk/sRP9dEus40y8U="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.41-alpha.8-tapestry_1545802466556_0.008789456500734483"},"_hasShrinkwrap":false},"0.12.41":{"name":"teambition-sdk","version":"0.12.41","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.41","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-d/eMQ4/hAeC8BIo0JsYO95C27S/f/lAYNhcX7QJi+whN+1ELlJzGzvO3prkHJ0buJBytDVBSItKzY22/+e0oCw==","shasum":"14c02fa147678842cd3273c3545bd3dfe0a3a845","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.41.tgz","fileCount":404,"unpackedSize":840730,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcIz/BCRA9TVsSAnZWagAAGI8P/1sTH7CgtWF6qGK/M2Pd\n/wD/iUavh2vc+9+1xwsBEnZg6CJfr7KXkPtJqY/3S/BxL3bKwOmRq8Ifv3qk\nn98f6BqRgtZ7vr0wGDVJXW5zPbJ/X2UxX+hZo0pcCJbiLBIgVfGmFc6xT/01\nRVZY3Z5i6+GO7v09G1XpQr9Brkbmj6pB4J8EdYEta000uSnDmHajkuJSkyzZ\ndZnjlrGqHa2hFi3cFBMQdVnRDjNaQduV5b7QD1TN1WLjr0fn954oMoQNQld4\ng4cego1AMGBs7DtnojtK3t56N/eB0D356NoR+SRZBC2lC9nkg0wLItmXom42\ncoM3jtoBxbIXEcJX1J2lo5fvsKz572DM+3ukBX7e5N0IhfiSBltCJ3g4rSzB\nrIfhXvlLudi+egpD8DY8lXwgjb0N0zXsO02dDD9bf5Y8VHwT5NRQXZowcI6i\nSuNe90LLITLaHf5svUl/MXYp8TEfL7ckuH04j0jReY2P/YcwkBHmmwbENqS2\noU+lSuqwoz+ymYFsMzxZPjdpZTkdbORYDtpEkXpaiCtRaPltmY/UtQuHnNqe\n/gAd+LImZA2kvgkiDhGQ3tNPQ0NJfHz/R3irozgB6cHLp1QyPaWhvrnbEJIN\njj/Dq9QOwZ9J6z475OQz/jU59xHPpG4H4fUKEklOmIlMx14MdmTNdvOjn39h\nmME3\r\n=kvVg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCRM9L0maOiPEkD6MNe/GMJg4mJ0j0OuEBMb/C/sYI+AwIgLbWhg6wbL4lEiSLi0t46hpnb1QwEL96xl4gPh6/1BOg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.41_1545813952569_0.40483819821845324"},"_hasShrinkwrap":false},"0.12.42-alpha.0-polypage":{"name":"teambition-sdk","version":"0.12.42-alpha.0-polypage","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.42-alpha.0-polypage","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-o8ieDdOkFOXVKNvfrm0pLdweJG/XFG26ld0CZu3fJsGgd+eZTPNDX2NC8xsHZz7C0QIL8NpnaH56kiMOedrTRQ==","shasum":"aac881c80d1a73b876985b84fe71f500f3d7b67a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.42-alpha.0-polypage.tgz","fileCount":404,"unpackedSize":853018,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcI0eZCRA9TVsSAnZWagAA0tIP/0G36YdUhP9a+kjuao5N\nM1dELIrGPSkiCLHsShm5YZThsfF/B8+cNF7f7ITEG80D0nR+NSt6CUHi1syR\n7fTJq19lg9tQt40gFXkt9RgM/oJ0XqhihvN6uxo499k7H9aX3sjBv0yrpq5A\n+wdQgm4goIUr0D9Ys+HxRX54Cr+4izo00y9H1CtvaLE3eCNZnyS62LtJeG92\nr8WW5c8AnbtptFXw8cdomohjF7Zq//WHE/+wxRx+ZKkncqPhMB/A+4SvX7v8\nHeGuoI3sz/n7qqppWD/dW8AVy4yYOmk2KgF3PKAy5IzfIdsKHbVDimqA/lK/\nFOMsZ6vO9Ne3Jlj96ORKrsNPm+vTCXz4D4cMWiHmti2nwS0zXjnLEFIBNTgD\n78ng7r4BsBJ9KPkYzHsj29LXWeQH8rUTaR0WqkYT9PfDPLhRpUt3hAaKwCF8\nPMLeThieoALS2MvzHKbZizaQuPs21hshuhKI0v6XsOjp/VN9riy051nlD8Lh\ntTKltWlkVDY9hsoJ9FyyiB/TYhlRqsPf773jDf+aOt83by4A3ELDILxMBnFy\n8absE2Ka+1TyCe90P0LWWwIWNvNaXgP55fHgFUqK3wYDBfFAaU+9i1i6nqzp\nzJBqbCs8U2TnnXFtdU+uu1xGyqf6Wigf0hBIt1PEMqCeJMSyj48pFXxtSYlV\npXML\r\n=Yitx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDfhxk5zKThNbRMYRRT8LLwg5QwPaK1zymB/xcX5zjOTAIgPkYD7frNBrySMcq/xmVHwOPjomL8oXTtYFNtsO8C2ZA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.42-alpha.0-polypage_1545815961008_0.07178715007163494"},"_hasShrinkwrap":false},"0.12.41-alpha.9-projportal":{"name":"teambition-sdk","version":"0.12.41-alpha.9-projportal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.41-alpha.9-projportal","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-X0iXYKx3nEIFUIMjaDWhOTX0Sw52Qp9OsMlOzVywLedr4hGYfgVhRQTj9oy2cqRVD+IylstGIc4b8IIRqwRMpw==","shasum":"e172fa431e3e23dbc39c2b8bca43b97bc0874d99","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.41-alpha.9-projportal.tgz","fileCount":404,"unpackedSize":852459,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcI1cPCRA9TVsSAnZWagAAbHsP/17B4XMN6SOQUpkHfWAY\nN+XlV9gAzuDU55qTvnI/s3ffCdYsy34cxdRspGdtF9MogLWZFV7zjr3RlX9R\njUapt9xe3hcDDPE4E4oYK2Nhhurm/vByjfnVhL1VTxF8ZheJSQPcroIytnRr\nbiCDtOe/LAA1DS4Fc1oCpeiNpXZASWXiRrlUilgl4vdTH7ohduLz3PmOygBf\nD8HLk1VC9hqCP0uzAowlbco8cJ1Tb+gl/x16SjwMGSLZAbMWL3PzsbYwuX1a\nhXVb6j0MK65NK3nzOxsyQ62IxSJABf8JQ3jbsnMzBIm1XPr17mIeukj65HYH\n8FQGGCuw5S+QvYjPfuVtwiflKqoAzbUXWaMur1za5inFCnUpWY+pz9w0/qYx\nRuZND4WJXsGfe6BSSNLGyJIOOsBVfwELJNR/c6xqLCc1qYGFeDRP8tZqoxP4\nBSpBUwJRQR38QP5Q2trFjP19Pl+jA1xNg3+ZWS064w8iZ6EP6ME8CQEDBOYQ\nW7Yg64/BDgD+x9yvu1haY12GpIJ86a3my4EtyOPGpBlhbL7UfWVgiziMeeGo\nSHLVpCOICCNxCWj+UxcEOWZsDZ6SGBokBBlS5pge5kdu9m0Uv1fChoawJuXD\n+Nz332PhntxYBaKY9DtIOYiZabYaq5FILGfIk50WWp/G1NlHyO413CtkncDr\n439l\r\n=Paoy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGotPUFlc4t5i7PjAjFbZOFtKZXRcQX+jaVh3pmKBioWAiEAo5Atr1AV0oRkCgGLgA94+amdZj2YJroUOq2ytgNwVMc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.41-alpha.9-projportal_1545819918414_0.4444605647490252"},"_hasShrinkwrap":false},"0.12.42-alpha.1-testplan":{"name":"teambition-sdk","version":"0.12.42-alpha.1-testplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.42-alpha.1-testplan","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-gxRavT1OvhnfI9qYJf/f/o1TYaFdCKTjVkmYmE8aNfsaxk76FlLZNFmPUjv7uTm3edSzZf0Nuh+NCzktEFazAQ==","shasum":"fe5c586cfb5aa4487f4f49c4469d8d9e4d0e867f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.42-alpha.1-testplan.tgz","fileCount":404,"unpackedSize":853537,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcI3gACRA9TVsSAnZWagAABIwQAKRUMyeZkFEJ9tlAQ5c1\n18ropX1ArgNwM1iBOvgjPQPoK+Ges9jpBBVsPcNBlgVeE7/ZWZY+j2xQwJGP\nPCVNYUtAF5fWrLxDDBBI0cFIpK082uzEEbJocfspn+SXAY0iZGtKsOZtf7VL\nMFWc0G2ZoOi5W84mGSkCTpWfex8v7XkAoR0hFjEF7i8Qxo0HqB6WXrxrZEg+\ndZWcqf6FDq8yx43ZeR+ckGa+WCf+h/X8joJg5DrHgJY+IrI35aIUAjNlb4ER\nXgvo4VE7leo7o5S5Pv6FkUImc+g4mfy7qEHZiRMZiqI/q/r7430/AH290ykB\nILX4IIe19JvTBPRZ/iLGcewYMTGIQW84H+Gkcno+DyARsb9j8TO2+J0NKO+s\na24Bglmqpnlv1/8iJrq/w3k2DfiMz4VvMHJ/TXIG7cNfLv0Z8Km+ePAtgVsw\n/Ml9nQVCJecTe/dVZKwoD9CLbN45pNJxcIm/5CW9A2DL83/j00up0VbB8sIE\ntAXDw7xZ0F1jAkNOMn/C77QpbBBKwvedfHZd6VFVa0nJAbtJ+4yZqzr9Ofew\n8ABXARRjo6WMZhnNug55yMbr/4EDVeeQlt8sf2fvH9WMo5UPVYgu2ANvXhMk\neKJEmu10JgqDAV0KOBWUKH5vSIIXIRMlwCbUrOQDvcj6NdX40ifVOMZ2DjqW\nC+Zw\r\n=igNR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDhn0Ocnooe0zB34tiznMPknDcjf7VIt5Vfa7Vb479u7AIgMxcKtaYH7JqX3TS/svlAXR+mpmqkQtzu18lHJm1Ngtc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.42-alpha.1-testplan_1545828352109_0.8881522555279326"},"_hasShrinkwrap":false},"0.12.42-alpha.2-smartgroup":{"name":"teambition-sdk","version":"0.12.42-alpha.2-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.42-alpha.2-smartgroup","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-dIcSoGztathkSZ6ZR6huszA/efIyVlirMZcTNEUPheuMRJy6A2aQLS4/VvX9md2ScOkKYzWSVbH9Zz3iMEQVLg==","shasum":"6946d0de0934793f6b2afd70c6b45273b59c17de","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.42-alpha.2-smartgroup.tgz","fileCount":404,"unpackedSize":855933,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcJG6fCRA9TVsSAnZWagAAMbMP/3J/6ZEasBxamD/kTxqQ\nl3rxfYsihLqyOMM3VYIeroDk8+HvWiK5APtODkznAbcm62jn8F1Q+mC+NBIE\n7Och+RFNMP1qeAYnvyaK8bnboAd0vWVFyDNvmGPzLCy0hD36v9zOlUSD42I6\nMlrB+RhoTzkpR2EHupNmX2/cTthWy/xbRfIjHykISWAvSiur6FANPbVi+Psd\nYjkTmtSq18QSm6XlxHUNtBlw9FKUh+I6MMOYGBwyRzqavLhGN/TKGDAqphro\nXjgGlaYJJf7abCQgd5eMfJ++wecPkPfewgkhk0ypNDcL/dw1yXj7egu6Qafo\nDbCfCd6YhZ9DR1Tf5EfD+gi7YRJhWcT/bbPkpoYPTFKmc5wFh9aLOZY5Bpb/\nPekFfjptvkvrfR4yEwekKMajjqsaur6Iem5XcIWgaWyfimsdJvmPVyUExU5+\n6Z0UQ1AewouLtkt5LUvv5SqLCiCZUGf9u3ajIUcatEj4b/9EKbRL5zg0XU1O\nG+rTtDCcZ1iVGYOOzNG5NIPSsd/bMnzvLb0EZ1jF1ZFDvnaCOV5gwpgEQXgg\nFPHp8vrR3qQciRqNVC9NoTDBxLT0+32ilQVBSv2y5vDLsAZTM7Iqk56mZMzS\nFI/Hob821Y9VLTRnvyYRw2EguaLRjS8Ivs6HxtwMY5bpENhS31oDxeTAVpAO\n/Y+d\r\n=9snv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDRTEJmuKNRKMBfXMNTtIUF0kTy4FtkRINUg6jLXhBXbwIhAPVfZRzbKUz2GHML/f54zZH9cp/YamfMO1JK08Gy77/V"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.42-alpha.2-smartgroup_1545891486543_0.4808164660450711"},"_hasShrinkwrap":false},"0.12.42-alpha.3-smartgroup":{"name":"teambition-sdk","version":"0.12.42-alpha.3-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.42-alpha.3-smartgroup","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-BNy1IdhxEll+EsWOjaap9ZtMV0lAF90ZBKuFgFuhuToKLtj6781LRIex1UhEYzos+eljzcP/E0BWsSN5N1uTcg==","shasum":"c5ab4f73f086040ba062c6c00ca01a32e020cab0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.42-alpha.3-smartgroup.tgz","fileCount":404,"unpackedSize":856420,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcJx2mCRA9TVsSAnZWagAAgmkP+wbrxyVvCMk9Pf8abzny\nmb/QkZ/t4zUhZvfLRFn0+0dQsDGgl5LICE4JYNQxoNbdNKnzYZHmECw14rbF\nmR+/TaAENDdg+wYO2cEVntor69KTsVC/Mo5QVjn8ntvmeqYrQ3G9JjnCT/r2\nZH5zKHad6C+Mk5KY6DbNiItSXEGUh3D9lbbw3a+YPLoY3xbDNaKlfbY/0yeR\nU3blBLFBn3m6gM9S/ClIY2OpjPixwAh1LfMjVrf1WScrGazHz8MlQXsJD5Fh\n7xc6zWB/gtcM/Rh1sgxIF39xkYnoM1zvEDmh3EeA94WFhwyjJGQnW963jqyT\nrTPbpCQqxe17ssHP9pwonmUVWTNc2up/RHSLs2t5GvMKhevhFzVJJQZ0u9Se\nRfBXdc7/b12HcEaK7iVSCQfvEgdLj8KW8VJoHSXnwlhkQiF/oCSxPtkbzY0N\nyCUcTTAT4lZ5dmTzL5Ly8H0KKNmeTZrevmezzKjSVRRr3Wo3xAyZ3pDGwXo+\nf5DyOhmug8gLe7jOGgUn6YDKP77SE5wvT7zXHFHShf5eqEGms97kYYnOg9DS\n9fYfTuqVGSPLAI8RGwiAy6pTTDImgDOMY8xwPCpf22t4Zkrxx3AddfmFJ7wj\n9FYbuGN7KjYKy6RO83IopXRcsBtuSxHDZA+F8lfoEAjeA3CYB73dV3Qlutqr\nnHbz\r\n=JkZK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFG6f1wNqoLwzGd4DD3s33BpyeUeEkG0cw2TNr1hVsgoAiBtWKtRqkc0MX5W7Gc9hBRV4uEUe0ggKF7oJIo/0ZzGzA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.42-alpha.3-smartgroup_1546067365645_0.9418161710103661"},"_hasShrinkwrap":false},"0.12.42":{"name":"teambition-sdk","version":"0.12.42","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.42","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-EnjMaavf7MkTgN+Yf0CUml+C/yiXHBLH+XSE/gv5ZT9al5g1+1e6b3jmeTiDqvvYSEhDyJJX07wn+ETzuAAaMQ==","shasum":"0f196006d91439b7fa404f912e6fdbcd510e6916","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.42.tgz","fileCount":404,"unpackedSize":853898,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLborCRA9TVsSAnZWagAAYFYP/2Zea3ewuKCJSHyJyT9J\nSgOZhNwYpF1tkIxH3SJheUBl/kJJqj8vG0nCGLUP7lvA3KlCGkO2lkh+2zet\npHzyfTrmkeVNQiNlfmMzbpVAB403+4CTrC4qNttX2MdI8BaxjE1IiaxQg2Rk\n0WmcqQrYJP6IW25EwsWylpfhO2dK3+JDJ5aaB4F2Ya1N8C0CfV3hNiTHQK5K\nS/6zXbWT9oBsQPUJ2PnSPYIrnFIAlQ8S+10gTidaN1Q8M1vbcpqsU9VfKKbc\nNHL0g3uKEZ/G8XTFoYZVIOynW4wBDFUA9KrsYIKD83dD5VkpG+wwoen263vX\nzIDtRS1fDTbFPsCkvkVwOGC8/8ymnASjiBLtu9wLtQMz/PCApDg7yXQGUCAD\nO7e/Jwu8d8anKgK0CMZsECoELsvKbKYjVeXkOfOigLAlv4SEDGjpnDjXpmkF\nFovGppc1ki/sMd673NOODF9FBQcLRvQvvvEKCCzHg7KUU35koQ6k02qZxd/S\nBTxpXciubg4rLds6Fl8jxEet53k2BMwhDPPMKnCbRdbKS2PUX3M70uvLw2vQ\nmO5JvCwYlCKLtbTjInwXZnU4JU+LCZTBpGuwe+tlmL1KH62FhcVGadc6HCpK\nCrVBL3XxpXabfZYut6ppG/FJLfJoezMYBj2i2ffk1q0OhmhwbNU1qHaDZwaO\nSNdI\r\n=d87q\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGfd8ELdGuObZY/FZ0GmfngTMf/U6CAl2I8/53U55IAEAiA230j/S2j1UuT3Zhiw4WmRH+65y4wiR5THi81kLbjSxw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.42_1546500650504_0.1710659456451511"},"_hasShrinkwrap":false},"0.12.43":{"name":"teambition-sdk","version":"0.12.43","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.43","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-uyz2QL2wFutTWqpKb08E6WtTSPD3g5XGmxRP5qQI5uHNGwFIyD7Nsf5Rotc7vF2AnsyfL5bqqDxyiD/ZOz2aZQ==","shasum":"10703221ca0d0a16f1faa8577cbd48018d9b9c8f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.43.tgz","fileCount":404,"unpackedSize":853898,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLcNLCRA9TVsSAnZWagAAi8EQAJAfEWuNlxHzuSETggJm\nPKX/CxGbw0+3isAueIj/eRZWl3nyZStK4+cKoRMMsjaUwh/NDhV5iK0f4IJF\ndedRPxMPuW2179b+BDoLE0b2Z7iednOeQEKUiDiH6TEiQZVoj/Qa/L/jSskz\ngOR7vyAHq7qHNJZgfgIY9hzY/jhCO61eUIUjzv3PXs9XaJVXH6F2fZngkEan\nnCD8oPqCti6ihb1k/uwhrBdBcR1d6+kfi1ckA6qBtzEKXGHhHvJJPfITFC67\npeLTK125bbyJf14aPi796XuDGGgH49PMP4me44BUc1hBXtPCUfMumLjxepmd\n4xhBlyWJbWBnPjzJZiCpGKueqnI7VAfd+63qSCrH90tSkyIycUPjH3+zF9Ty\nvQLr0JYQCd0gITwQdCrNQB3cdF3qgBt3Bexx8HQ8O5eLmQHT2ho/U/2SINBj\nJqmzKe582di8Yp+LA8fGHw6uA5tLOQpPSp0A/B1x9k2vbb69Ixu7KiVUgO/d\naGULyfNxv87Xm4HDnKnRJVjPCAv6VBF0JZn6ynwvivx2ksPEvl76N2Htiott\nDtnwCFAM1vLm2kktjl6qdcCj/GIA6nM2nrA2f9pM5JLSQSxYmKF6/2vWt4f3\nca2Rvp3J6U6zHRCKW4dMZWqLGQ71GsL+F5EjI+YZpncmWH7kZJb+qLarRqVG\nVwb1\r\n=lgiC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAQlujiH1nExp4UohFcNW7bIQRUJLaOVt6/KuanZJHcJAiBkJAOKSt/2opq8j8qh0I5Ua9bsc/v7R9pSNeBE9srM7Q=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.43_1546502987036_0.05074986344321153"},"_hasShrinkwrap":false},"0.12.44-alpha.0-smartgroup":{"name":"teambition-sdk","version":"0.12.44-alpha.0-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.44-alpha.0-smartgroup","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-nAXJqrws7WH+JJ3R6Mv6286GxvPkvcFrrZRlK3GtxzzG71o0VqKyH1J/gQZvkHg8oGV44VTXKi9vssrAjITsfQ==","shasum":"ffa3b8572ac31e7c060e8039d3c2a19bc1defbf4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.44-alpha.0-smartgroup.tgz","fileCount":404,"unpackedSize":856830,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLflpCRA9TVsSAnZWagAAMJYP/RupcASeu7PutkEZP7d/\nOKZVzceVb1QjFQX3vDz4O+ogSGeVtutL41KFs4wg7Feebtyms25lqLhwAGHJ\nmjHB+n+zF5HR+NhnJK+eadF0wzZlEhE1azsumSm61XYGFCX9dlFAXiciVMYF\nqPitqmoAZ7yJr12pduT7kFMU03UIO35MEl9TuoWZ6H4GmcYL2Gh2TuionHM6\nBhJhYqSN/3tIO3m2aiCmSXMRigZy57ie2wGyv/xbgSyv9OgCyGrJwYZLk9SC\npXxxs2rMezeoZ55kcKU40gheAKGOYbDobFVc4fxpArEcUn+Q75UzVnMECOHG\nmd9UET159Vq1hy2w/Q1KqiDHiSKHd0EjQaGGsVuzSqz4Q77jecs8yl56PKmK\nv2+R8ty9y4Ixswm0Cph74fZOkXnYlNZ0GvJ8hdzwqk/PsYX7R99oCfkA39O8\n3lzM0mmwU7V/+SS2KVzQ2xZwyapVkAOB+jwLQLNaIIL/2aUMS9xQsqo5bObk\naM7tkKMOgLz8L4deAAK5tEUgdGLRFW5sGtrR2nc5einfQky3O6qDAZt1Y6jO\ndwGP9rv5HboeJBFZ5KO+6Q+F4o12/VLANEznnjPETCfyXw+mLZAVU4oIXtTl\nXoP3uQonQ/32Y2PbdljsxVvtqvFwZK5llzGQKCSfqmcjEYXpnJLMmmw/QtQT\n/kgL\r\n=GylR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE4P4+jwRyklpoTEQG21u6JH2b5KS0bmtFIkm11qW14AAiEA5s7EnPxUkJoDYsDm/JiESGRf3SnN8XwBThP7b2BGctM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.44-alpha.0-smartgroup_1546516840593_0.5654726285598335"},"_hasShrinkwrap":false},"0.12.44-alpha.1-tapboard":{"name":"teambition-sdk","version":"0.12.44-alpha.1-tapboard","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.44-alpha.1-tapboard","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-HqptM+/n3ABaSjNpFBxW2+GXLXyjbv/HNbALQWE0wULkDchrzqtlkSRU1EUH9lBsB5bqWTGbKxbLWSL9BGqDJw==","shasum":"c16efd0574df19e46192c59cfb75e511114e3d36","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.44-alpha.1-tapboard.tgz","fileCount":404,"unpackedSize":849229,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLyz0CRA9TVsSAnZWagAAkhUP/11Vm7drnCdmQg19hZAT\nNtq3FXdBZNsgo72NY8BMbyzEZ4Iz5CUlZ4ZmcYOvXTqw7esmct2p2xTBJgzR\ncMjRxEU3GiKkohuCw4gLLfHw1l1rV/bAfzH5wU0Yec/621KkWzgz/CsBAHjd\nBeLUVNDZqwVlFFSRakt7lQbEArbPbON6Ob0EMCE1sLftJNh0GjABZ7mST3hP\n5T0Ts/I/arI/OwVx0l8kCo0U7k3HlD17pmDB03IkeE8LS0zHKay2Ih6p1xSP\ndRgGS4FdBdmMb+X9r39olsyBbRI+0qw073LVYDZMY3X1qLZxvlPEplRQh5hc\nnrpwtcOoxZk1DPTVuzA6YsbruCzXeOTx6dJIoA8Y8P25zvWFJV/Bk0Aon5k1\nO0ovwqyOeumTU1S4kU58/3yUqZXNWPwwedKJBMxiYwJkSQtv9iO59F0yKRNr\ntLb3U2sPCIVDVYw4LiJrpvXiWt/0axGZtkdFZorrlcfVFcI40CRFSNQmFAgi\nI77DGN7aVe8L1loUq2UwfwH4wfSFGon56Ipt2m9FRyz2xbINS9BjdNmkCqSa\nQRdbXfCivPMXgJ2ntbQhqTo8+taZynMwHC4S8ZZonHHa1B+x36gbH8dA2a+B\nan6CDZfVQEkrpGCIR4N0UpMFquA+8cC/afpMPSbvjn6Y7oQi3qzXlvHp9nym\nBZlT\r\n=Szuc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDr2IJIE/dTzKCmCO748xN5dX21IR9dgcmgzLVVhDO2ZQIhAN4SWnCoEeVQPo9FJvapXW37Tlpc7dDODK1iRO5fT1cL"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.44-alpha.1-tapboard_1546595571546_0.4283844809501258"},"_hasShrinkwrap":false},"0.12.44-alpha.2-testcase":{"name":"teambition-sdk","version":"0.12.44-alpha.2-testcase","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.44-alpha.2-testcase","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-yD80CnFBlmnmvtswGftoe1+813ZdXPLrzTnOhd4lUxDzQAf8oqvvnzGFMoo6uhHKU7BTFD9driATae9jnwJU/w==","shasum":"bb5f0993db0bb14614049146dd7d924f0324eca5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.44-alpha.2-testcase.tgz","fileCount":404,"unpackedSize":854377,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcNBt1CRA9TVsSAnZWagAAFRcQAILx28wM1TrxZFK9TUzW\nqb/WPOsgfF5dlYpEzitaZe6nqQnbSLIKkHCnsINPzHEc6s53voBbCzM9S+II\nENFRu1bi0SAJeWKFGOX1+mrX1JFfM84+hdoeJyOXXL3kNqn9NxlhM9gc7hn8\n8uo2fQZf5kep7ZsheKWXcUxmHaUt5tQzZjI74vnPDqqyYLwXWexZh/UETROp\nqdoZjVPtZqlpy+gAhvbFnw9uy+1wXIjGuHiTi53cJegDpXVuYNzwN/DhcrTp\nfxEIz0hYNc+YH9csGUG5xHYv6Rt+6P/WNV0hLSNXeGfApOFwbI3iOVgffsZX\nDraNIZsOLx6m+NfnE/OFnTLPPWCSCQwfJFag9YWCZ9kmu1Q4wIdPD0BG2FKV\n5D5F1O/ojffis3a8cflX40A6DoyyFsQn8oKs/q0WYIFiEJGpasa58tvtzCSf\nmaBJSyBtVKVsOpuFSV1UL5Im3a7yqlZ+qW47fyUBtmIGmeTk8PgHEaZT1nYK\n0v5sHbSo8d/nFtIM0ykbog1430SpZjslI1FWyet86sYBZl+mRcy4gtZFyVCz\nee05XAoFR8atxXucSYGjztEg32eyAwJjUz3TPgHfR0/+D6UoExhD3nOLC8yb\n6OUiFxiZm9Q43Ah7QeWmTwxrHomLNfjm55Lnt/WuhyIe0k6tMG/ZBMDaRfa1\nbXLC\r\n=0187\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC87BwVwMdgP/F8+VYAzGFrrJfbHC6UnIP1erEhwIfLEQIhAP8QdwhzUL6QoYDi221UcfpXEh3amVURtuE45a362YEU"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.44-alpha.2-testcase_1546918772815_0.04281558422955034"},"_hasShrinkwrap":false},"0.12.44-alpha.3-sfcf":{"name":"teambition-sdk","version":"0.12.44-alpha.3-sfcf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.44-alpha.3-sfcf","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ByCr4m2JDgImoxGzHfHOaY1B7ORwo4IvYHqrLJgWs3QRDzP4pr3pUs1L8XOwcC60aigtjUo447e7DWA+F0/hAw==","shasum":"28342e66c8b9b02de0eec79e53ab7f1f2aac725d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.44-alpha.3-sfcf.tgz","fileCount":422,"unpackedSize":883850,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcNJ6ZCRA9TVsSAnZWagAAl90P/2d3RK6IDssfU4iJvlfz\ndNBD/XAD7lKnjqIyD/WbsbvwV5dlHiHxH/BAUMwLqiMx+Y1wTLEzi6vYUsAy\nl5M+A2JU3vVQOtlnk/JyrN0LWlbBbT7jtsfTgj1H5SnLHWKZLAznlq4csldJ\nckrelRK+W0/pKk6scGdFIIB7C7Hyl2iy585lRKMXMzP4W3FqfQbGkmMqRf3y\nPXqiy6PVYZoNanoscU49rK55oLOdAgWaoSRrFmcwiI6KH5vwF4X0/t+OfexH\nVoNTOMWfdnt6NAt+El9QV9pJUmfi6ii1cY/62JCUfiLjBm9MaK3tufKatfpH\nrEA1gPjYmlUiK0rUMwq/tD5LvCgw6B5w3NX2gLgtXasm4/XVOsskhx2cXA/l\nbM3SJHklnP7N5njx08Mp17qb6Z7wg8h50YQA4DpFg3vPjDC3vacISiweVB1G\nlHSzQkdRDOFLXGcEtPUsRMWfbm+fRMZfBTXKjv2R8yfLOfAv+CFPYiQ9mIPd\ntziB7xVK99orc/6vAQtyNqJVzNo5GDtVofNAEu90zEg8LnA0wTARLaLrFWuu\nw5f3EPn5GPm/TZeIsRQLdmGBzzaYalr4zRADakzswWXJkxAGT2b6Uam+XcL0\n4CW8D9mVZWiU6Nu7+Ki6n+B35+mpC6zkOrxENhV5Q113sLArdRZRMdyaTfCw\ny7e8\r\n=rN09\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICgtej/Np7K1RzWaCc8nF22+xYSNURfzbJe2bbO0Pb8SAiEAy9hKtsIl2UGJjBqLYRe/uSo2G+04o2IhK+Xhyr2axZE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.44-alpha.3-sfcf_1546952344391_0.8100894545867561"},"_hasShrinkwrap":false},"0.12.44-alpha.4-sfcf":{"name":"teambition-sdk","version":"0.12.44-alpha.4-sfcf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.44-alpha.4-sfcf","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-Df/xdEPhJyV5ayJV9HeHlr7/q3SthkMoWsY2rU/OOIWGpDQVaGrSMr+LZFOGuxlpWn6WXJMxkpp5AWtWs1K+Jg==","shasum":"92ae24ef3b338ab661cc828f641b109f57b102e5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.44-alpha.4-sfcf.tgz","fileCount":422,"unpackedSize":878771,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcNYm3CRA9TVsSAnZWagAAExQP+wb4jpquGIBb2T2wBBZd\nnpOMM+pmurCFNBaVngMk2WQLmUcnyUqGg7WjUhqytgFw1RKw/7u3A8F6MmCS\nzz3yiDxwF1tWQRPvAIr22qpTlp69U6xvIU0mHSlwYFNiGaVvjl19JYBlfeFR\nbflEliUiAv1ueDagYoSrl3E3dvj3Qk8Okec5E5XkTBlGelH9lOqJ34FaLW99\nz1hczy/RVYEpOFjaJ9TN6YoIe0rtiiM8tGKhaK2g0nwdiRu17wCZ4cBV9iFA\nF1Jb/cQI7QQZU7VjTi9qapH+7NTtR+lVXuWKT6KtvL6nOTsEnMJXLynDDt7e\nicE+L/C7d5oQQYMiSwo3PBuTO7Oxr2l8Px6PJT1IAKyh8lcWVxRPIWvbUNZo\nV6HaAYqRhy9kZN2Sqb2+eYEc55fEL7CQBxZ2EzJnyXnfkGUzHQ6weh2tHEo9\ntVjvMW7J51eeR/iGsUlr+TBnbjLceOgx1PMGAr+1kkxMS3XM0ZvFsPeIdpIg\nxmNnCKXCwSkSgH4r/mIop2dtDdXeEioO8CoUQhpPMTvE2SHDxsAg+DI2+d/W\nu0usHj+lNwm8UFlRZ0nHK2SdZFF2cTTw+EVF6TxEWr/tOI08mwMISXvLotsc\nIWQTLAe2c3iTfpyB8UVwCDJJc0LJOs+Ic0bK786D/CshdV56cBsovU+uW/8A\nhH4y\r\n=S1eF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQChqIbEiyqUzgpzrUPM08zJQHG83QUDYKd01KVLzUfV5AIgbmQ7jQyYOXySNiz3bJhqvM1wEkXsDbsomoDGJJhY6Fw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.44-alpha.4-sfcf_1547012534885_0.3883030265413665"},"_hasShrinkwrap":false},"0.12.44":{"name":"teambition-sdk","version":"0.12.44","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.44","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ZM5DOe1osXUaVMME9MM279bzmSVq7dcHiRbXUfDY/1NqplLBXPb4Jv9bFFwohX43QcHy7+SNXDBohaN8qt0tqQ==","shasum":"ee48343a0fef4938a07623dd92ca4d48a6c2b128","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.44.tgz","fileCount":404,"unpackedSize":854360,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcNbHGCRA9TVsSAnZWagAAhhgP/3Lxzlzrg2vMIoB5NjA6\nF6KKJmGGUYBKf87a8sTcACnvJ0l9Y82InI/a+uEas0JDHpjqlyW8UqWhW2tW\nVQAaucRLNO1SWGs1W8P0kZcvafcId+tN66rS/UkqgNZqWF+S7vV1GEKMXnoo\nbh4vn9c1hiLLqxleCmh/odCbg/JzVdHKt00H8fnchI8bMWF7K2ExNsecOzIl\nPrZMl6k5lV+4fjNSaTnOxk1xUBpVRssdYGcIe8Hhj0/2LDQFXngnKPD/nEet\neuwi9j1qcXAYUaxBH0RG4i43yWdvTrwbPCHvF5MabSaqs3JQ+6s50fL/12yx\ntdt321pkkT258MT2Cs+anJj9xpu/VJQKXmiADPcgZ3fgw9ABIwzJI2+5qAOK\nyCxCyUZ6TTThG2h293pQxHWN0z3/ysEnB8c6AzBPthFCtbh1l3NE8WBy3lvB\nGUNBv4wmSnubMI1+k0kTVJ7/keeRCpb2uMJxwbt8jxcDOg6zkgiQ+/t7pLnu\n5AZk3h8N6YfppIi6MNOm9kyiJvXHoNbxdoLX8z+FxdqfbxEc/ugklmnd3jce\np9ocZQSauLAMylWnHIg5JKlal+Nc+/zrMEYYBS/fNFGjj/CnHwdCatp18eh7\n1nqCIOyqBdyyhZRg/ytOYdQ3/0VYYaYMdkTNP+cSBJFU+WIkqq+CnGksvHr3\nCot1\r\n=anG2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDVW2DW6k+D7lcSVqS3cdr9MexWQi4mThsxF+/YDhf/XAiEAqfsFrdPZ6kOiV2Qm/s+L+8HgW9FgEM6RnyONjb/zyKE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.44_1547022789512_0.8803895452364554"},"_hasShrinkwrap":false},"0.12.45-alpha.0-smartgroup":{"name":"teambition-sdk","version":"0.12.45-alpha.0-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.45-alpha.0-smartgroup","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-MNMPtUDSCheJtshpfwd96fvnTYGx2sUcdmsdJe2tPDAy/EGEUgAffbHzeUvlMD9NMnd8MpQKWbmgSZz5aAxIxA==","shasum":"a0b7c981ef101c71bd1faa16cde79e57eb298977","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.45-alpha.0-smartgroup.tgz","fileCount":404,"unpackedSize":857292,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcNuHLCRA9TVsSAnZWagAAzRwP/1FQi6Y/4shCwl2fXVy9\nL0hV6AwJC9yH+K83zRZisNZESuK/I4448+/z1dWGsrlYa7Lp3ofq/UMIwDbD\nTMt/e3GjNjYdHEdrQIMeXkbHugyEIUeDH/kEwpzcypEiIqts76K+BP4Bi1zB\nHAMsWhLL5J/H+LVP2NgEy+fcoeBGuq/3xyW6pDkd89rgpYurCTrotnrE2Bsn\nVLlowEN1h7ugcAyCpk3v8l/eGqaPyr3BKm+4ZyTqW6zfye6BcsI2BQNPqmr+\nzuBQVd9CtiTCYMG3qnCllNdIkLaaEeCalsXNTuPbDkEf8M8W7fQOR8MU9DJI\nkerVcHItUdDkp3hCbBS+phKEEs7CoN88eAq+kqWztxYJuyK1EGAxWSgWCTf/\n4LA4WVfOm2UY8VRRbvjtAqecBu3toPm8NqZr7CNbjldDZ33ogf8ikMUgIzFJ\n9eY/uZs1YpWZbpkyBARjanECatkvp12pgtKz9w6KP58O48/boKTJusoylsLW\nmk79Vy+h7jyWglhfMUSao/DsrWO3xds/wTzqt2Vg3APUvWDcwT6cDjAu3FN/\nc9v4T6Qg4lxmb+mTTxrox3HH5XC4yaN2FaoztuyvPLGK8tGgmKI7B3NsQptQ\n2pbTQMYCKTe/x1TX6UcsxIizYDwj7oZUOVb2b4s0R1LnvRItOHNkxnFWd+4C\n3icn\r\n=FeBC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC12ZCd2dfK5nDg+ZoSFrn9aSXNnerQC5T7dlZx8q9KyQIgOY1AY/+ktedVdRjuxQa5kY8EPRa8PPJTbXZcDbdqjqU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.45-alpha.0-smartgroup_1547100619264_0.9558910659112867"},"_hasShrinkwrap":false},"0.12.45-alpha.1-sfcf":{"name":"teambition-sdk","version":"0.12.45-alpha.1-sfcf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.45-alpha.1-sfcf","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-Z/sCYuF+HVpBIWgWYxQEWEmUQs3ZtrRxpH1QHze83kpjiL0J//E5S8FmSuFE7eaOHRngK0X5X0jRahiKMjOH0Q==","shasum":"cd139e47a6028d01b51dc1fadc30f620d6d2da09","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.45-alpha.1-sfcf.tgz","fileCount":425,"unpackedSize":885837,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcPHcmCRA9TVsSAnZWagAAKycQAJmGCCXur4/lxI62qU6L\nlfKp9El4TAjwxga3Xc3V7Yhm6OR4YGwq/lCqD2CDoJPsZGtRpCnPTn6jrRZw\nlmCPNrbaBLWRy5Z8wmLG7zq9748M950sWEdqlW/l2T3+FrpOz5sw3kZIdxNW\noIkp+6kE0QgkMzTdIwrZUXNo4WY4p6u1/CTtx4+tnEHHqh+unT2E+HVocGYH\npBzH2OAGatS087vrYGQNCbJePInNQQenilSBObpdLn65XBzke7/X2Uuex6ps\nf0Uc/C1/qWgIVdbZfsbN1Bc8NXac8R2pObBPmqYaQze7jRjPGfXv5lFY3Xly\nGfscRI3sZJP+nbSAjiBPuUs0k2iqU6UeNKAsSgsomGE26BWUN6H6UT/BaZpq\nFFRzf8upYwbTa7iae86yBC1xbaNE2htDrv3J2XHifxMksBhF0TGLGDKShbk7\noI5CI2tuGmPXMI3ajTvtst2k0IU4j2IA2KLm6Gk6VAav071B8NK2SBPrrWce\nM1s2Hffp/Kxd4Nxda1WIlAjp2oRkYI1SNDR8ZE+KiAeMWIdcFwZxxXmSDPuU\nVomLLMxRe3Hot2IijPraOw3dIfkfzlcsj7DeCesY46SoKiSHkChQdLnyuQxe\nK1vM+fBYiD5jiEH56T20u+ytYTU8Q+2ySo/Yl9wAAjZdIJCLWSu0lrGD79z0\nn8qy\r\n=JLkU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB7yZ7GOY47J3UhZ5qr+7VDeanjGu3w3/gwrg0fJnpx3AiAUPA4zCSGlODcZ9I3Y5GHek5TdLqNNFi4IZZzDwWniIw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.45-alpha.1-sfcf_1547466533563_0.9959410260153634"},"_hasShrinkwrap":false},"0.12.45-alpha.2-sfcf":{"name":"teambition-sdk","version":"0.12.45-alpha.2-sfcf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.45-alpha.2-sfcf","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ULlp+R1PLtlB48E7VfaWjtr2dYNwlSFjIDV5B/COfvQcZS9bwu4VcZMoVwkYVcN1R5bn8MLd+V2nITRhl/a0ag==","shasum":"9ae63d010ab1544dfbfd7fe3e38eddf3c35523fb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.45-alpha.2-sfcf.tgz","fileCount":425,"unpackedSize":886841,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcPW96CRA9TVsSAnZWagAAznQQAKNhoVbQiUwMSFP1eXSn\nRoO+Vx+Vkcu8haSGztgl4d476fDQdleZv65XHlBECej5MeGkwsjRaNMu/kMn\nBeblRbzoeY+Z+p7F1Lviug6Rt+R7hRPbSDLV3ReTZa5lUmCz/aUSEg/YmHkI\nSONx/6q304BnsvmQawdGdJVK4TAYT7scYtUGkRi9X0wZT04DwbIcgCGZpjft\nbuJhVfywE+OHyzvg0H3wbGofN5K0iKd8ZztY573I1DeVRB2gjVlGLCEQhzHp\nAacI5KVd4z9sKjQT5YOGcyp/5nY6Oow8oRPd2XTDEkcn/l3k7TfeVWcTO5Ow\nHvMOwaJw+RRXagaxlvyyxOZgXeKhf7sJ9ScoianB06ZBqYp7eA+3bqsvt63+\nBwPFP6kCJavJKpybfv4IG7zQGBvWDiLi1QGW+ikWAuWjwFM7nZZFkhtTprWe\nFNbTS+OQ4cu6ndG3iLYBUNF3BeffIXFSnjoxdnOTs4fg27y2ZfI9TXtHrg4y\nQ/HW/3tp7yzw6HbcqzSLosepQ8vhX1dA3BIoklZIF6U8uOKQyBS9IIxTqHKO\ns9rIXhNHACf/rLsOpoXJBQ40xprxlXxn6iURYgYp3xqDZ+m58L9cHroRWor6\nC7HUGYgmeTZBWhOdOaPCnqVAyr4a4DowayEsjqksprL8ZN8EWeIs9zRoiYUp\npgUA\r\n=ou1u\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDSQWJPkpfNckQbmz5EnTSvHgumYABfJMkpud9T3DettwIgMWQQgsF8prXDOVBZAWjfUXBBqU0UbMby9MaF648XJ1s="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.45-alpha.2-sfcf_1547530106057_0.1976336243961161"},"_hasShrinkwrap":false},"0.12.45-alpha.3-commongroup":{"name":"teambition-sdk","version":"0.12.45-alpha.3-commongroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.45-alpha.3-commongroup","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-gWk0C6ay+zvjcEFwpH5nT3dmvPtaurbEaCjHvNfXYUMBTk5hemdJoK8seJz+lttoMlgtyo2nkksZMMz8jWao+w==","shasum":"0ff740ba3fcf37150cbf562cb24549bddfacf5f1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.45-alpha.3-commongroup.tgz","fileCount":404,"unpackedSize":854916,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcPvnmCRA9TVsSAnZWagAA6HwP/iDmj1i/3IUVCcIC1Bdg\n9XHYP2eK9a0T3cGIPLY9tdDsnrT5s6chJSXFaaRkUV78FmmQkXEK/kLF27ms\nbMCmbuao6mVefCPUhygVvbYWHacFKWatpjMOgUzzj3ZnpHUjpyzVSzPfiA1N\nP/4LidpSiPhiQPYsr7uxeaO30jBUC9j7kPAakJoXS22kWHo1ZcuRAhBI+4zW\nj5mo6FjalvxK4fCr8Wp2RoJN9Ecddn7mZasXTvuIREgFbgkxqYzR5ChelMCX\njaKpTWoJ241Ra/JaqKGfzR3soy8HOfFWKB6DAaJyT8OiczGu+d9spJxiIyOp\n7qmpfHBZGZt+zTA7KI2K+wCkX5e0+yfD36jyyhJ1qYvvIK7ARx5TcqWz4jGp\nHLR6b4Hh6Cbrf70phu7zOVfylnpmYkPU9XW9xzKOwcIRQztLJUNVnPmz5MBf\nINql769BXvrBsojUw5/iz5Zl/rj/QYOrKJyRnBeH46S+QuEGM9hUqt3OMlC3\nKEoNuCL3VJB1JcOLnkzIkTNEzqp3MTSlYNDNFRjX/sGGTJjznqnZtDPaeyuv\no98q9B9pwbRA8DXP6KwTcJBULJeFlI/zMPo+GeIvuZN4L7A4unRPi8lUB7O4\n65y/kzmTGN2arhea+kykZbW65lUFNK5L4SdTOeO1y4CsJwwgRAsWmWj546Qt\npbcJ\r\n=utba\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDMtvB1MQ2SyrOiZD3jvX/QHYH1FDpL6LZ8tv6R6zfb7wIgBUDPj46RxTScxCykFSPoPvz4jgNRYlUOgf4JNdYQ2ak="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.45-alpha.3-commongroup_1547631077425_0.8352834917271634"},"_hasShrinkwrap":false},"0.12.45":{"name":"teambition-sdk","version":"0.12.45","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.45","_npmVersion":"6.4.1","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-pNMxdVzLvu+F7VfHtZV9om+TEPrsSqvr4rxCmik8G1kLXsDkGXrs/0taEV4HRikQeZNCZqKIxNDJkuTse60D/Q==","shasum":"10e0462afe876ab365bb3b69d4b4d1e08757d756","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.45.tgz","fileCount":425,"unpackedSize":886886,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcP/IwCRA9TVsSAnZWagAAjocP/3KCKondc2p2DbzJRRS5\nTVeFAnrbQXr5hxY+d81coa9ATzygq6QioAfqap+ererE7pOAABfj4izKDkV9\nGTpPrJpidcoXRS961Ls45Mt208zRS/eEPTetgOOdCTBKke+50K4CvZ1ZU/NL\n+LYVudVjd3aFQIV8Xz40ptTJ12K/TurNX4GqpCqO+OC1k831Z0KJiOgmO0ly\nyIkpi8ez56rr+JkmmmVzWdCj5ugXYrOzBvCqDCSCIkVqiMst1GT1/m7AdJ0s\nvupSSblnh/SX+hqX7WI0djS+5EC+XUXJft0Kwz1sIxzNTV8DXkPBmt6pe0IO\nqCveGtEJt/knDriqJRgPRNIyPApXVTxrcgiTNviIayrBJxiIpmJJUexmxX6a\nCeCbQ+IW/xaDZzIIcrEl6um8SMGtUkEQ0eEBGTU83g0+N4qYI+cdl75fyJaT\no5ENAn3dusFKw2dXIoH83VkfikkKdPPbVlOPGEmC9jgDacp3h3YLO+cvL8hG\n3Gms91Q/vhlvIygtT8QBOHXveIYrtxEMbLEkCOnOZlLvNRtlViGIlbs2Rau5\ngQ3REcvtcj10EShd7Fr91Dl74OkY6JzWgplgWmk36E5CGXni8F3rL54EunEr\nSlBTf7pSqW07e9x6lsErLMaVL22ZZ1TbuMKlxCy/y9wCQRXYeIQ6JhUzMWQi\nB8+m\r\n=zBzS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD8nRZfhDI0NSaaqzj+hqqA+MNBAD/Dql0pRWPI+NtgtQIgWRAKbxhk8yfxwAXBnqQFyIdGs9SGFuoqiCaukNVgs8I="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.45_1547694639802_0.5223595586821705"},"_hasShrinkwrap":false},"0.12.45-alpha.4-scenariofield":{"name":"teambition-sdk","version":"0.12.45-alpha.4-scenariofield","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.45-alpha.4-scenariofield","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-dT3L6KOJDmA1BBBoJR++oI7iXnKL2EHonxZIVTf5d+rWrVCs9ZqYD2bTnMFpSIHbAn7I/Ux3vnks2D5PVcNUCA==","shasum":"883adf2ca59d8d2a163fef99f40234af053f927d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.45-alpha.4-scenariofield.tgz","fileCount":425,"unpackedSize":888818,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcP/1qCRA9TVsSAnZWagAA5SsP/0sH0u69ORDQ1Q0l+cO+\n5YeMQSF3BwZABA+d2kTLOvrcmOIp8iGidSBscLA5kEeuUgFUbDXqz2iw39kA\n7ojZROG/VFMdwLbkBAGIpdpBW8UdYa1CIk3TKsMIJxrplk0uzur2kvzauP47\nH67+Jt4/7qVBCYZjjeInQgPXs4Qz5oV035sfBycyAY84dimJrPFkLPY17zhp\nfY0G9VIK1EAgWKG+blbVN2ew1RmbXvqyS0gVdWXTwGMK6k7a8j76K74wUtS2\nvy9nnZUhdIMNr3vmTbkLPmQWeczNlr6rF64VbehbfydCIZSVyuIesIeS3VXY\ngrLz7mWI9bW1UT+vwo/3qfJEIbi7kUu4u2fK/KWs4+RJM86QTpylzJJ+rcBf\nAgzeZMNWm+gaHr65cljoo9VrQLYao3f07+Clu7MmQFwIRoiaS3giggpHAR5Q\nLXMPg4kdpqCaZymd/W/EHRmsqkdi6eJ2L5NEXUZHYurMsCU5YZPosfclYSUi\n1D2JFsYvh+XPjEb3ALCO3gAAqZSAeimPsZfj5m5TAfbP3t0Glv1fm3hOwjPI\nZUuY4qhMBTkkY4VdQU6OiaUTfYmvXCUy/lujl2ZTptfOxKjN+9e2EDLoogur\niAeblRqmrRt1GXcj7LEeMOVtwqErE1YhdS135RHsGzljUFZexnrvHEAg5wZp\nf9wM\r\n=9aDB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCaP2FdwV0+slea/x6uUowEZZEtNQmig7jlhsc0u5L/XgIgPUGB4arV6zqm2SwNwhMLc3tJKwAcHa1qa2eaDhsEGJE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.45-alpha.4-scenariofield_1547697513792_0.5894271565074987"},"_hasShrinkwrap":false},"0.12.45-alpha.5-scenariofield":{"name":"teambition-sdk","version":"0.12.45-alpha.5-scenariofield","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.45-alpha.5-scenariofield","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-/C/VALPShMqG+JQ0CRIrqal/Wm833k6cD3ID3NeLHRzb34T9yz3IF3m3/ivStNldG0hJHsWa2cjlmClZjiVHMg==","shasum":"d29143efb64ca432eab96cf440c6f864c9b7d9f5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.45-alpha.5-scenariofield.tgz","fileCount":425,"unpackedSize":888914,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcQALRCRA9TVsSAnZWagAAoUwQAJT+rwWT/kA/BGA+1rab\nQenNf67ojJcCcJSrWQThc34kQqE5u5DE56fIhrSrr2g/FbgIPTJGdjfNcdik\nkCs68b8AQV5+X9irmNUJt79YetvLM03OQ99kjim/E6OiKqev11PMS9hR23o5\nRXfGoenlmWjAzAtij7cfh8UMPHPbZmz0YyBvRoXqpaViECSN0H/VnmBHFPcm\n35fsls4SDUcUZD/LaRwnmhYi2CAtxb+2cSoBVqChJ32fKhULRZ1fSajMTwHx\naHYMoB0BfQYJMtoRu7idgvYrRVc/UQzZFO0H97unWMsgSZiWbV3QFAvrMWNo\nsQAKcxxjtb8BAy8SKgndmvzlLyDJzmCFMhz7+js8EjTiqg5ZU0n14uEQVua+\n7PZG2MiaBM3QCCTd0q5vBpjl+Vi/3gf+m6167youg/ptcmTH3EnmTA20WJ6w\nfRnnmMwre78Z5myVUzdhaCF8huSwU4tAVDDybwzImfh1v9fNH/Yw59ETtBUp\nrG60sSaXxuZQzvWtp/D92+4Z6m1KLuyOiyuZ6hEVPN4xlc7XHHtuCH2Oz9/M\nAsPQ/AppXlPxoG0eYaHEoeRv9XJufeW8VbXUro1sCjgrZjWJ8Jz5ucY4IslC\n+tdboz4jObhfOHpj3LeIoa2kYyyKMVyzU4BupQhkTB6n2tPGjKJw+ZWDYupB\nQKbP\r\n=U5sD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCfmOhqtFc97nmso/4if12TYIBkmYk+ukkiwJhXIAz9RgIgM0paYdlDEluHFBVA5h+wUmOCX1HrYKg92+I9ofX6Ud8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.45-alpha.5-scenariofield_1547698897027_0.5997281818332478"},"_hasShrinkwrap":false},"0.12.45-alpha.6-scenariofield":{"name":"teambition-sdk","version":"0.12.45-alpha.6-scenariofield","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.45-alpha.6-scenariofield","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-JpnSgScyxTFUutxq6MrWTykVTHzHxrQNyIwWQIwgSyfz6OqEbz5TIls3WTCa3OWSELlXuwyEnaFCuh/ExUZrcA==","shasum":"88169bfaeb2b6d61089b80432a92d6bec80371db","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.45-alpha.6-scenariofield.tgz","fileCount":425,"unpackedSize":889317,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcQAUaCRA9TVsSAnZWagAAsHsQAIheJmt9FIUK4G4EFW0T\nZbfIZl3GoTisc9jVnMkBuM/6EnHs5qw2W09av4ThXHx292LQbpO8I8e+0BKK\naKDpdF0wx7iwruU0Ni/6GgBT28OZcQaa/aE9TB9oGC0zRF5Le/B9v9iU4RWc\nEnJW3lgk/SJL5wMsce2vKi8MGvgtoI7sdiquCGlAL7MaKs4EiTTbiGN+G4/b\nqB+mfPpWN55uduttbu8UzO2k/wCStB16WGKrvRm6lyHB53ljesVCA0cmIYBM\n2fAmv+hBLoY4Vbo45J7NTXolEB3xOfyTIITOHzVwdq34VkPHIE8fpyHM8JJ3\niYF/xvk6PH00nwTvhQd2pypRjH64AekKbnLjsiJE0LYAJY+sV0qV+5XMWwoa\n4/bnP69XxyKe+t1GdFd4BgNu61DGrXL25zYQXegR1h1CGufZmpiCJQsiApLY\nXTJssli/mIpsQsdrqL3yORnEAuTHnrfA1ogp4QjtOS5BIYA7F2TCm4VU6Psl\nYr3WjzxpiPunzkv+y6uBSn4M0ESVJXssrLSCQi6OCwBmjO5Qskt1l9EuJcEK\nQCGmES15E9ZgUOByExyjBLVQh3jVgXB4jIeY9h0s1yMXh1I5zCUYS3h9p8Pb\nlVY6Blzgfm4rFc1rRQwvLaVcnH57NLVEqknoyiLfDqw+yN4ey8+r+RV4JO4T\nIiQE\r\n=zQC8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDHOnDWs5lqa1glOlMGRBKHj7oucLKMMYE5fz9lHlHifAiAW5qp3fvzFlGI2jyPIrLMvtHkk/Q9byrgDt0jKH/bcJg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.45-alpha.6-scenariofield_1547699481659_0.4751792549876839"},"_hasShrinkwrap":false},"0.12.46-alpha.0-prefmd":{"name":"teambition-sdk","version":"0.12.46-alpha.0-prefmd","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.46-alpha.0-prefmd","_npmVersion":"6.5.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-MBQfpAf1Qk/GvEqnVX190EBOVKekAFIb7oPLfFvst8+HEgKJt6f2BbgyTbcVhE+Xxsvxg80kOqE1fjjPbHtBXA==","shasum":"604240777abb0ae466f077b26501a0f14a0f527d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.46-alpha.0-prefmd.tgz","fileCount":425,"unpackedSize":887202,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcQW5HCRA9TVsSAnZWagAAcssP/RqHw4Al3S+MFazpW/WZ\niDKetYldwGiCa6V6WH1qRkZGAhbL9Tdoph/zlg1ubvkLc5eTWF15061inVDc\n68HwJkebfmYk24BwvAjOG1bNeWahF2QiGtzX94TOMt9dhfK/pJxi1tsg3dPr\niyYvJzxBhESGKdwWwsbYPvNjFGL6Vy1Nq61meqXK76phoD4RPl0RAkoymxEX\nENIhXrbnQKTz+XFoMWGivIA1xKJBFVDUJV5c8lhjvWOEzG3QeaDPoQOTtKYc\nDsYOWghok3CZFxW3Ol+Dauv2xGpqtfw4+h73UvSMGtIX22/XWiiCHSYq+4YL\nJwDOfztF8NqaUOUyY7GYUupldqTJE3jcqQ1W3a8JBd09MqbxYPCRdNw3NTJQ\nlGnbc1Wmy4wu7uwSiO8t2UxhDowbemIId5Pv7Az+DRRUCz/8iazaPuLMp6cp\nRP9uNit2QkL0dm6vbnqwH+3/czblwRv88/VuUbdeACifFUpBsZVgcwauXvzT\nIoj23MjLYdP9KNhThih0DVAz6kQuYGSGO8kOD98mVOqvlAjPgMeiFTYK4trk\nGUEWtzrwD3LGEdugdK5bE6KbvVgHEbQkZgZhfl7EJs78Pi+DRVzVhRWT0TKR\nnoaV7s1KDYicqRdWmxydoD/r0+jEJCU4nMCqVwh45eZ91iOYHMnHfKAh6Q0i\n+17t\r\n=tDqm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCwqCbUbmFVRgpcCLc6uFozxND0tESkbZudlbgg5TOUYwIgE095KFlpC5/l6TCUKzvAZ6qdLd2AT0t7P1bF8MihBFM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.46-alpha.0-prefmd_1547791942334_0.8534496879182492"},"_hasShrinkwrap":false},"0.12.46-alpha.1-cgcf":{"name":"teambition-sdk","version":"0.12.46-alpha.1-cgcf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.46-alpha.1-cgcf","_npmVersion":"6.5.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-dwwcI4lloVhkBtcWq6r8pdHH6dc8z77H2lQxqybyhkAosqsaoxQYJj47tDn+h744cpVjw1BwUrIQOXvjpfE/YQ==","shasum":"d43d2d4edcdab24351a93431d8df254861f6095a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.46-alpha.1-cgcf.tgz","fileCount":425,"unpackedSize":887477,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcQXEXCRA9TVsSAnZWagAAwB8P/3OmDR6Af1sTkrOVIWyi\nRwCNdN7tykZ1B5GtWhmj5Vlb73RMBEe9UpAMsNmpDRfxQgkfc5lhafkELFB5\nrwTOFDDVT7wFlk1uPqEw0Mo/iOUsVDKS2P5N8Iuz0LaG0ILyacAjmAfkABIY\n8Mt+EOJtd/yz7acBdUMXpOPHyujWMPOvnEySNdE880W3Xoad40e9ql3bTjyc\nExAr02HgXuzKmdJlaORyzl8CkzHCGDUEdOvpOZuUCQvQtqWZBlntmJrR5ghP\n0WRCC5PdC7Fo5boVJwd1CUXo7mehO62GIKaOmbsKBZ3kt95N08WjkFv3kMtx\nZwUtXKwU85IvW1rzJd6owG4BCH8PHWDXbgna5CS3nCAnnwsNaNBvu47bZy1b\nzLtxCNF7UnZxUyETWtqwRKBqnuQhiRWk0iB/5rSVvkVbuKL3ztd/gw2RfNl5\njXmACK6oNE+0sb02gAl49Hxq2KWKzThk+e7pZK8TU6UsZXhY5VXFjKjGzvqM\niPFlfwk3GGmf2x/jeCPmSo/odXMEzEKCUUsdsbW4vIR+5nt70qcCFCyvQYJI\nFAgKfpwTRS5W2MQz+28JC0HApYyO2Sje2mMC/W/8aFoQdzIA/ghnOgCc9Rmw\nrsUmOOvJYBRHhHCwUYiQvTnaN7NPnQNDWgwavTpzt6qwQjAwJroRCsoKOk73\nuorS\r\n=UC+C\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCiwEVub2cYjfcD0zexiQUQNjfcSSHep+Ja8qMncaF1igIhALcNAQJkiD9KEa1wabLGMOAWj71Kn3UrWq5uy9cqdn6X"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.46-alpha.1-cgcf_1547792663219_0.37255768971638914"},"_hasShrinkwrap":false},"0.12.46-alpha.2-smartgroup":{"name":"teambition-sdk","version":"0.12.46-alpha.2-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.46-alpha.2-smartgroup","_npmVersion":"6.5.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ZcldTikm6aGzKoRMuItaiMkuTAm4b3hxHglMbWer4cFmBOGTpZ9NmOWu2H9E1eFr83jH4ID7ODPeAmoZjGIsrw==","shasum":"0679e7eb924027b535d5eff667a53e875805d27f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.46-alpha.2-smartgroup.tgz","fileCount":425,"unpackedSize":889818,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcRTbrCRA9TVsSAnZWagAAe0wQAI0DvBYwUwBUoCwOHN5H\niS1/s18SlKTrJCqJgR2odlZNkvVad7xHNxKvVMvgt8WQO8Uaez+n58Gnwieo\nx2DbspsScWuajb/saOrNmKf9ykU0s0xZCeBrlbH3ikGAzhovyrXZ9ZLKsVQC\nt9tv2fVn9uIvFLm3YYrUcJxrb81hYAu81UwCczjSan1eVGBMDO5sMehzI//L\nnC6irouUtJWaGrF+YYUwXKxI7S9CvjkdmqbFfMEDwZh5LBHK/2kezAM5XXUI\nIR5N/OGHN4R0eAjsPnDEx+qW8JIyECUsB10rzmKY9I7RJf8wUfIFR65MAlRN\noojbEwSpUkFFCQ77GrHHaQrYQVHCQMTWWW0CYDRDUXDGFylxa7Qa2Ccc2jMT\noHUxo1isqMJBz+f35RteJ1S9jWZOHiQ33RW9w7qO4Jn8GQQibOQdEqEByxGg\nHh7r3yycATlUQmg5WAsmm7iS/EbEAAEx2OQTM1/BY32OGj/U+gyH9qJud1Nl\ndN6hlCnnCnFkNP3Pey3YJ0E99OtQheoNcRDFXuzn54kFTqstItw5edJGduGG\n3EwuGeYtZodrX87CIf2MlXsImUNZXzSTnujs0/YhhFDTyjQcscHju5Zo9pBp\nhjlv0Ga8WJAA9iiYQWViGGISoP+30ioubm8Sx+6MTZsikmI5O5K/YaXGj/l8\nWmkO\r\n=/McL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGQ5KiZtwUJxOBzjpkVUO8A0ABkOc9NdLj1z31Dhtb0JAiAHaDV8tHEkubEjr2S2xw+jy/lOobxBetX5n4neeGYaGw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.46-alpha.2-smartgroup_1548039915049_0.3858947134224584"},"_hasShrinkwrap":false},"0.12.46-alpha.3-scenariofield":{"name":"teambition-sdk","version":"0.12.46-alpha.3-scenariofield","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.46-alpha.3-scenariofield","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-fkZbHO3FalWx8NIwsGHZ1mHptfDsLAhMS9mwOwMSABQeH89fcKSAgEVJJS7W9ARvpMi6r5w3lhp1q7Yb0TBG0g==","shasum":"4edfab016ca568f0287c5b517ef19a362c8a173e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.46-alpha.3-scenariofield.tgz","fileCount":425,"unpackedSize":889557,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcRUDoCRA9TVsSAnZWagAAGuYP/1VaVUsuRdV2oLMjlNIQ\n+epQhF0z9lh/MsSqY1m8RxoF+LT/M9ysJ7A93dCMyWyJP2vYi/wzumZnHcZ2\nijTYBdmKdf9NNpogGe+ae60GK6kGxlz4b1WLDFweLwUdYyU8DdpmIppIDFsg\nc46n2n7gBxNUh6VQsuhDdXrEPsy9YT522HaORfq00+mEroVcVtMSe/mQAI9s\nLBrzHBxxHOrvIJX6N5LNDXIwGAkLD9UMn4WREAUlPaVFz0YoiUIeM0OAdJSo\nzhHhYkO6l+Hivl2x2l5BZaft/hqwveam+kmzKAJ0q8uxZBhCfG8L2cvrW+es\n040odD17YB+deWCoRHm8KaAifyD/LKWbNjHf6OTTpD/3vVW76EkV52VMW5dD\nH+o90lEld4VvwieJloy1/RCEwdR9MfgXL7hTOKNQUWpTSRIZGM1Ri/Qkh429\nmNtew1/FO3AYSShlf2K4siJTimNelE306G4gUjxuSmQj5ibgmNeAhV5DX+IZ\nulrLKZmGN/Jyl9b0Wxp4t/gchxAxMim4T/WIvOzUX2mx0032U2tuO0dJ3pGU\nj31LXnSdO51tPRqJ8V0TEYkH4eJKf6F9XoSPIBh+jT9YrxCatAeuId8IbhhQ\nWJX/z+sm3SfjV+V1kG4BPMxlvSkUg1gcnDd+kjDXr2jMIjP/d9+eUl5XAVvI\nlcKM\r\n=0+xK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD5umvNlcF+r84rnYKnAo/D9aiyyAJK5kyvMjMkS4ypiAIgCOtPWnMyKCads8YnK2bmVqDZra/aCMK+fz/MYgAOkQ8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.46-alpha.3-scenariofield_1548042472239_0.45688763024097523"},"_hasShrinkwrap":false},"0.12.46-alpha.4-tapestry":{"name":"teambition-sdk","version":"0.12.46-alpha.4-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.46-alpha.4-tapestry","_npmVersion":"6.5.0","_nodeVersion":"8.11.4","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-o01ID8zRBi+QccDS8IspIGjCokI5uulWeKmD5GzpPE40y3f9oe7l/W0jn+Vyo7cDfjbZvsKgabbqvueIi5Nv3w==","shasum":"bcf42302adb494854abab2d52318ced19e0f74fe","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.46-alpha.4-tapestry.tgz","fileCount":425,"unpackedSize":885477,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcRWHGCRA9TVsSAnZWagAAmgIQAIOcYOMBzs9EVAVozuQW\nyJ5CFrUmcqZC45yN43n4d1QWL2ReyKdSBx3tCaBhCx1U89Dkpps1gveq9oD2\ntdUB0hYu3qkuuw2P9Y2ihsqkBtKPYSro9iQxSAXsI1wmenlNC5G5r+meCViz\nskE84qO3H0x7evi0e49OnUfQwhXULSqVhfpQsTrE19yVbwBaub41hstS9eGx\n38hCy8J+YkClZv3axBEwy758CTWRJP1weyPle+abgnBzJ+CmX5dUqnbp7whS\no/RPD5qV2bwfnyw8iZcswAS8y1vJUPITT2JzkK8ZD8ckMZqPhO4BUxwJxZxQ\nmPSMsqI3AZ5ie/0QXQ4FmVKjGFpm1KYrUeNxaJQtHQKtb1jwmeEc6xYS1l4n\nYiYzpDt/LKJPmievRg2eXyVTj1j/E49DxUTnm0w0uuG2abcSXaWAEbJTPmM4\nkZFhefc6ioPSVcNlVmby/fiOBoEgCkiJrVqmCGXJO717iN6QBsCgXltmPSn6\nMuooC+etx5PHAcEPKqeC8vzLSDfuuc4lipMMKBwldv+GZ1msoxuBrm3Cis7+\nzshlfpaMgri+tHulYB+znnaymTqCquF8aaSKr8a64Ej+/idijt+0mQAQjGeq\nG4xeSUKgshuj4uqsGHwL0Hv4bggrQDq4Xw+/gnzkefaQmbvyi1mIY7E+UmzV\ngHkW\r\n=6x6S\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCyG4x0bcXykuT3JLev+TL/WE5U+DiH84HF/eJUN7+EBQIgdl7woXBlaaNEWCp3dL5oXovAn7/0H411XvBE5bRjqc0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.46-alpha.4-tapestry_1548050884951_0.4881921891017629"},"_hasShrinkwrap":false},"0.12.46-alpha.5-prefmd":{"name":"teambition-sdk","version":"0.12.46-alpha.5-prefmd","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.46-alpha.5-prefmd","_nodeVersion":"8.11.4","_npmVersion":"6.6.0","dist":{"integrity":"sha512-1loQ/lPz5HuZtEMJoTiUiT8sHswG2MSjZtFT0JPt4mIhlOEFtDXLvNM6k0YorBegEa4fnS3TwNxmydxJvqvftg==","shasum":"eb9e1a85466c1bf7f9666e49063af346d5db14e4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.46-alpha.5-prefmd.tgz","fileCount":425,"unpackedSize":887228,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcRpPECRA9TVsSAnZWagAA/uUP/3e0KUccjI0vOCsR5mUn\nRRnJUS/EqIzZ9nYbZ/6iaCuYkPCb79QoVv8v48YMQOF4Cex5cbbxBlwYk94f\nznyI05f39iRlrW5nUa/X+TAr0qaYrwh7xqwc0FT1trHATlVgk2fmgk00G+Po\nzlqOwzm6J4UYRXsxUpe+HDlHXDNJnKymbLcF8oYSrGFFiLaw+aadNimF8dW7\niP3DQFkc2HmkS7j0sJiG+b6MFQ7Dzgfs8jPJzluuRv3AW59lBil+YoXTQxAJ\nU+uPSM5RDGYGjXJu7NagHiWt3diwEojh2suKddrgvlAl3HZbK2wzbbjZ1NMS\nJGVAQnLOWpGb5SllqANciOG0B+dA7RWwpbiDETx9vShvu+51iUXNupvtthm+\nlyiESLxV+Mp9rj+M9cLiHndm/R7Ijw9YG0Zy3d358r4y1QDR1IanKytMjakm\nWawFUa8GssxZ2x0B5TU/4UgvfoaOaI+ffCeOyMcKvjygS8pAZlGb6HgegNMQ\n7+xXj/62vKzbVXIXjAZVHcYqxKPp11f1RM8Itd1ay3PfMcnO7ujdG8vNelfC\nam6+GiJ4rIzHWH4xAVn8TFTw2PGBKE1X9iEYb5OVd/xPA5eUpTOWzosEjSvV\nBc/+Giy+UzwsxcFY2n5zctapJ72yRBNNLwUlj7GVxG+cw/FhLE/7ATia7T4u\nkjUX\r\n=R+20\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCVhVOKGaQFwUaJGgq7S3u/F2LNHEO9r0cehb5zndlpHgIgDoWP+8xaAth3zorc2xdy47wWl8U0w34cy4FpNkbNDC8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.46-alpha.5-prefmd_1548129220187_0.7491454096898629"},"_hasShrinkwrap":false},"0.12.46-alpha.6-tapestry":{"name":"teambition-sdk","version":"0.12.46-alpha.6-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.46-alpha.6-tapestry","_nodeVersion":"8.11.4","_npmVersion":"6.6.0","dist":{"integrity":"sha512-x/zMzHVMuvTKnVQFyUH6tVoNwnsgeOhbwVERyaMDe8F55z+YUnJceqHlzNtW3uzNaWYF4c7JTZNT+JR8yfxWSA==","shasum":"f54fad2a241bb3ed68f060f5651d905d9601d767","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.46-alpha.6-tapestry.tgz","fileCount":425,"unpackedSize":885772,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcRucbCRA9TVsSAnZWagAAfJwP/1Eyvw0WvzWC9ttM5O1c\n+ZEDFaYwol61Av8oU359U2rHo6q/5SRyAI7B/edpj8lY8V4+g1B3ml5FVP47\ndvW/UnpgODjyob71CRq2nJPcl0W4BjLO34XCFKvXBji0YoRirUCGD/jbb1mZ\n12L6dkTYOpQ5NKyEVf0SjT4Fif0LssLEszSNPtHdpu5kVwyyOjfhQOmWiTGl\nxNv2Rjtu6j9JBR+3EKeJ+y5lxjV2tuEvUqrnVCsdLNs18YnbBeQ5vhgGAp69\nlIrfSxYE3XDRiiQj5DAjvg5RydoZdb40CiL/dEGxoXKApBe28hAdwSb0uqz2\ngfgQNdvkMCbIZZpA3epEyxHqn7u09Bn7LzjPbLz1K6xJ6ND+9qN/sE6RQzFO\nJPDETsD4jQHkmNkABMefW8FoGVvGOZ3LnA/vkvIYhkJ6ui7WNCfTsi8Anhgs\nRCL5tiLvf+BcUAVOT08f66NgGWgzM6TculjCtQcNZ4vX9rFMvsE1KX/8NDbY\n9fDJOPYdw3bB/LIBcO0lRJC+vT3sU4mwI8WbqBpJ4Gi16f2AUSoBvfrlAp63\n9Qsz3zp8WvTgWVfTOb2TYmcRedwufJr+evtfPZg9Q2vzhkwMbBYeJtBla1sq\nANLSxvrUHblb2aN1RAQVlVygJ2d1ffPV15nlu7uGqZQiPsA+bEvG/qpOy7Bc\n5Rzd\r\n=IGqU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFVRwoZCU5ohT53sgjgBkb2yuRSTNtKaXC3stx4tMl1RAiEAh0agXZco+u7LJNs736NO9WU7X2aACH+o0uAwJQeSczQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.46-alpha.6-tapestry_1548150554297_0.5508618415230477"},"_hasShrinkwrap":false},"0.12.46-alpha.7-cgcf":{"name":"teambition-sdk","version":"0.12.46-alpha.7-cgcf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.46-alpha.7-cgcf","_nodeVersion":"8.11.4","_npmVersion":"6.6.0","dist":{"integrity":"sha512-LeAgZMQ4FlpKAxhlja0GR0It++iFfMmVMEckFYAhpcmGULmRlCP0gR13d3Ni0qVenlMLu5sCmIthbuUK/YOLug==","shasum":"be2f7cded507c1384be12486632b4a7ceb2f1744","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.46-alpha.7-cgcf.tgz","fileCount":425,"unpackedSize":887733,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcSAWHCRA9TVsSAnZWagAA444P/AxmD+mIDCr4Ihe6/5WH\nCn2XxwyY25vDvec1/IH7Tq4xiM0ygiUjUAysaIgeb3ZejXLtdW1GlfLpmq7i\nWQ50aXIgYyssxRRf9IBQxgjKwa25h3xCDtLUVn9L9kGoltRXz3APZXLQSnkr\nagDXxWW9RohIvl9myw8vYDLnBDzzpgJOJjyt4CocgLr6FCC6RO2nZWvOSkd/\ns/OERRjUTpDZxgXPK4WtiQKOG3Ajvo46p3PooyLmN0Ccpv97AHk3lYpbpIe4\nOlVReaQ0FjhFhVc5NDC4/mkhiTGHsuBTpm5u07Y0eMttPhGWcMjdpNCcNr4f\nenKz4oM5IxwefqnarrCzACq+9wMvNev65Y8XyEZ/PBLdB1O9GGYBEuda/wHk\nutizsqbEmqaddPFk/i/lymrH1OCGi4ZykOPUUhhcuKWKAyIjGwTd6NdCi6cv\nS9xJ7hnu5BZujAKTl1xof5ff0GQR5jA0pXrb1ItQHf9F6ZAtFEV7QE4ECBSD\nhSXWGVtb9P+41H8pZtbI/s9kYiI50Jmeirw4nhaN6MmHpnwhNEZ0XC8w2DVc\n4OcOR829q0l0sWLG8PVCZB2axaTXceVb+kPOZfyDMoszCkFul90ElEmYCQ3Z\nKzuxvIQMEjJpEtsx48J0tXI1wZYwu1E0YwIJ0x2F6L7QZyduKw9UO7kEU1k9\nI0s6\r\n=AR2O\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBWrR4vBkLs68Qze3Dy+JPJ1jkBk5A/ewkl4VoK1gCB2AiEAt9whRRU9ElrD4AF8YWwWYOwdq7v8ee5wydl/+NMVZmw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.46-alpha.7-cgcf_1548223878676_0.8554734003796756"},"_hasShrinkwrap":false},"0.12.46":{"name":"teambition-sdk","version":"0.12.46","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.46","_nodeVersion":"8.11.4","_npmVersion":"6.6.0","dist":{"integrity":"sha512-i4fAOvOHOkdpoqk16FuY0BWBS0q5dwhglk6AxdKRrzXW10To8wcXcDttupuWD8CdDh4whWJjPW/zZhxFrk1zpw==","shasum":"b06078353a82b9576ea13867fbf9f4e69bd9ded5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.46.tgz","fileCount":425,"unpackedSize":889876,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcSDuXCRA9TVsSAnZWagAA8EwP/2OAV+TLq/tc1Ug0G71g\nkDVMTZvjito/Ec9wi/MyKi8O5NwKVr+vDgG/5G5X1D/crmHa6ZqDmx1CTEwD\ndplCPZzLvPH8pfieXif943FMLZBimpVmyvPYTimDhnGql7YgKtb9nuFnrZki\nQaIM5Ei+9M4PwqFPicOBhQqvIyJIOeC3x5boZqbqzphMRFYM9TrnXq/9aTCJ\nlAeram+md4tCf2ytj0Wiud9/6Qs3IpV9+9+ptvrXXWqL680JyGlIZhxdnD5+\n1cpGt8sNW/sjrez8bMw3Laelo8RJlP6E4GxlW7KVJ4JcNnTz4ahgS+7M5Gtv\n7Em6Ta+IaiPI5+Fke4+4zV0mkdONzZuJPG81ikjeS4pUhakvXy0PJAOhonWC\nAZ0ldmfYXHsDIPpOWh1/3nrK4UNws36LyRl2mR9QNoABC4nlo6GRuKa1PgLA\nQdRjET6nubL76woYTv5StW21e5SWeElqiUjJN+EcDbOtYoJKC2dmUSvSo+a6\nOsbNgPHwDNS6QlM1m+ijkSEvzgO8pODCxLgCkHuLeM6npZdsjfsvd5Gpw9+s\nVOIHScYYLr5JUexySujgwWThFaqUjc+1vDBJ6WElwIVumrx0DceJOX53VuMC\nWqtgNJwG3eyBdDxyYNJHQB5durWkyECE1/21DkJSfGVjPg3kLI9pMDWEnKHM\n1xFF\r\n=0j5b\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFp2ui1DNj7rKmPCMoi0DzeZXSdJTnhN5XA/o3waJf7DAiEAud2W4xJaeBhAcq7m/bl3dQoSP+hvzlkG8qItKG8a/gg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.46_1548237719017_0.341166426735966"},"_hasShrinkwrap":false},"0.12.47":{"name":"teambition-sdk","version":"0.12.47","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.47","_nodeVersion":"8.11.4","_npmVersion":"6.6.0","dist":{"integrity":"sha512-q9qP381/tbwYDflX3HVFMroNJ7gI6KgFbBDbtNXaO+LzZf4ScQGdhO+IssFkMpDrj6RG2NKEdQJrE7XA0mPh+A==","shasum":"4a06c4da8c2641f378b9c011865f13832e0db4ad","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.47.tgz","fileCount":425,"unpackedSize":888747,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcSEtYCRA9TVsSAnZWagAAVTUP/RHQC+3nf3utcAHX6gRB\nBUEY2DrkTIh74GyUXTF64NyyyltFfAHOwhxRw7ru5Mx0PN+0f5kw+SAe89cV\nR4xhW0VBoLX0rtHl+MGUWiam5kKN8S0Evaalad5/qogfS08CXtRUoTDlPXsL\nzX112+DwpLcbxq//XKwqVYzMn8+uqHXiE7kFM+BZ9wt33Vr/TAXQ6jlFT/GT\n8RABstkZGbc9C6rN1Nb04v71dG1axsJpiHOTp1VuBu8nxvUYP0E9EwkJpqEm\nzf3msCplnXfLfij7cuLn5pfpnJSmTSzPf4VDFDnger71FmmHppl+3JiwRNRx\nWZCrYMNWZdGbHu5GhMM4cogBbcwxsrPMA1IOhZLYZUKVuVUzTctzoREOR6Io\npZEB62vt/6tDKp+6thyr46qgVDd8R8wO9QdkxG9A7gBrHnj+ioqQ5TMff2Jg\nvv+alF4wji1XK5zeCKram78WCrO2vVSOt4sIg8P2oWRXryXhIQ/7RrT0+y2E\nLlgrA0Wa5WDpL4MuDsm0qSS3+PFOY8aWu9FyAfZTMW2xDwDyEfy0n9JbJsp5\nzFuSsHS2UzPMvSeRxJE5Y19B1U8UwA/r/i51NFk6YooGS6gwoerQwFqQK5IO\nSK8k0Vxmkeb8TKASVS4Ba8VN5mYhFPnsvauNM3P2K7hOJAVOQg70w4rwluvU\n1JoN\r\n=ypJ5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCzaig+t7yeCxOgNgOR0dXLwl4lUgb0aN4T2suC1Bb+ZgIhAJNERfEvUSR1kIWD7vCu5++xTMkdEaT/XvyzmRHvwlqw"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.47_1548241751732_0.31518339147296337"},"_hasShrinkwrap":false},"0.12.48-alpha.0-projsrcid":{"name":"teambition-sdk","version":"0.12.48-alpha.0-projsrcid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.48-alpha.0-projsrcid","_nodeVersion":"8.11.4","_npmVersion":"6.6.0","dist":{"integrity":"sha512-FzYk+My0WxSsGWG0V3cIMQ/HXcHSt++r0Kg/PQC+ezH6aS93x51an0LL97iHw6VNPQC0ruhdyIGiFGvJsz2Wcw==","shasum":"9532c3024ee02fa338d2747264ef52eefd765941","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.48-alpha.0-projsrcid.tgz","fileCount":425,"unpackedSize":889058,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcSSEPCRA9TVsSAnZWagAASBgP/3eErIq5CpKKnPaCrgTl\nQQPgqmUsxOR5vxhuVraLrWNs0ReYjYhLHIXfaWjGSLc4pkH2hIFDXJDOnGbu\nTU2ewTbdvcKHDDw4txAagwcNASPcKb+eUDEHYWJs6RbAlOGEQlkuXbrF9VgQ\nioe+fbVwAhHHXNnfFQYN7i86/cuTO9YB4Nyf0cIu1lGkRjjAvyvncSYdf9rg\nZBJkwc4cm1uvzoBK6jQ0QN7DlRDzaDgYJ6woARwg1oEmdE8MtwN3Xu8WKin1\nHs7/qFK8W2xnhf6owpknJyGRZurD8dHsROWYEqzPbcNBqg03cdUyXVJft/Y1\nqumE6GXcUEjNhoP4T13qhMj96yo8/dfHHu+K5eakST/XrMIF+EDMiP1tJkWw\nwTCEIBU6ejrGO8MqOyxHzTkGxHb5hJpZ3iJW7TAR7SPBKappzwDW5DGzsE4v\n02cOFDEcqea0nwIBoNnvkxTHG+u5JylMx1mzxMFN0IkS7djuH/j5hFcP7DNx\nhGEMRiVe0WIoHJ/hqbNmGMaC2aoW7WIc91mgTFLEIqqnT76DyMlEMb0Z6Owm\nZYonIqpBpJ+mh/EvN9I+VZkigmSOFHqbkZ9vSPVERNBHDGTzx3Njf+MwHz/Q\n0qOFBHl5iTJ7oHus2/0qaChxR2rnGTNyKvGLHHKWIgrPJTrHoOY07Eulc9tu\nRS3E\r\n=2rXd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF0hZWn9T2LAzABv3KuJUPXlWVk6wLM0TQzrn3yUnw1GAiAnGbDv7icAYjfeQcQAk5fvne8uHpEcqH0CSDjmyXL1DA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.48-alpha.0-projsrcid_1548296462172_0.44243669449746004"},"_hasShrinkwrap":false},"0.12.46-alpha.8-projsrcid":{"name":"teambition-sdk","version":"0.12.46-alpha.8-projsrcid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.46-alpha.8-projsrcid","_nodeVersion":"8.11.4","_npmVersion":"6.6.0","dist":{"integrity":"sha512-SD4nln+Rcr+Y3l0aEKUy1g/sotSaEjhMbyhovCkoVu1GIUfUkY/cXtIo76MxUCeb93sIyVoMSa9q0riMGud49Q==","shasum":"3cfc8a0704b0db602df57c24b6c8c99889c27b6b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.46-alpha.8-projsrcid.tgz","fileCount":425,"unpackedSize":887197,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcSqX8CRA9TVsSAnZWagAA2MYP/1GAqiLtSiZeMbDVSQpT\nl6HLfo4Ma+uiuPBVeScoDhpw/dNZPcGFQQjSVOwlTC11jnXnaBt3hzNB+6vK\nyzenhPS1h3kAu7j126pHDBK7aRlrzM8WJawLxx5cMM3Vui7bPpyipbjBwFCK\n01nSZ5wYnupoX+8Ssl88mVCZ8fG3QNFRUUhZ4uNqLNh1ky3Qzb+mhoNhRqlq\n9wqIGPaRgeC1W4sfw2a5o/V0H2LSGx/NazhmqUeDka5dfSI0GdNWekT8KTzD\nA5nLVfWLhkwILwUAQzeXnS3YmgResaHrD65CR60sKV3s9VVhOmrV+Aw8d7fJ\nuES8DMzg4WAZPF8YaRoGsUaOLuLT+27wWH0qQXjbuyLiUlWP+bJU1rtWhxCY\ne6uo9Ksnm1+dFmKFEsHyt535dkFW7fzslGEYfWsxAOFsZxm6ZvqURKOaOGt6\nrjJog2iEckmjjlFxKnn/LuA6R7cn5jj1+eYNHtFX/OJLirxJunt3J0QTk5ct\n3we3C1rYzU0HdRQWz4JuVimSX4/3ShFIuJbQ24yNRKZVwbrNEl6A4cYmghde\nESFn3gpYTUzlk/pkwupseNcGKirmNSuApYiXKi8hRKSav5NLm3/LQDIeaDbK\nuDA9BvGg6+ShG7h7TCJNtjq5+UH+9DK4ZMEQof83DrBXZUS516B71l/aUP2T\nS785\r\n=Tw9b\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDlRT8wenaRmiO9paCsYpwg3kdq8HuEay9JuaPA/UIH5AIhAOFGPrb3s4WqaLMrYuX/8RGkT9OgzQsVeJltgCASbwnS"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.46-alpha.8-projsrcid_1548396027537_0.31429374221782824"},"_hasShrinkwrap":false},"0.12.48":{"name":"teambition-sdk","version":"0.12.48","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.48","_nodeVersion":"8.11.4","_npmVersion":"6.6.0","dist":{"integrity":"sha512-ZbASQE2nJUEBvZJFq7W1WCAkWHgnofbR+ZvfwlmzC1MZWYEfe3OefrGhRcL/++nF5jSVHRK5jKf5mIcULTefdw==","shasum":"5507f00ff075667fa7bbe38b50778d2085719897","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.48.tgz","fileCount":425,"unpackedSize":889040,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcTqKICRA9TVsSAnZWagAAcgkP/0JjBQSLrSKzKr7E3JRs\nmURUpQKDl9k0TOogjRZ2BAgOWy6aFrCZh27TZZjme6/MFXiILIj3umAEgdnN\n21wPif25ab8vXVW55TE0Sj4K0ZrnUW5A6lx1CkqhbQ/GGqrhKDg+nnhJcD7J\nLB8rjQBoaa3SEq8Zd9yip/NT5PQrHljb7GgVnESBi+FmQe4TwiBLztVCzotL\nmQQqx89ftF0vE0EdkumqoevIVU9XrnSm8T1s5qotJDHGB8jSXzy4SwH53oZs\nBVrjSr/VFsrxXqQyk1cG+RxHps/QAUxpdozjSe59rBYY4BzsmZfniG13t7Fh\nTaBv8Wqw0x+DmOdWkAAGJDEKEslmtrKLoKkTSDGsK97k7XnVi4KHxvpyBXQR\nhQ8w5IJebALaWWtEJ8IY1Ptkghv91TfnL/T0VNehDkMYDpXJ4fElESfuWaur\nR80THDCP29oZlGWecczXIAjm+gF8O/CHmxGYwdY3svdaHZPDcVAy6DELNvSS\nnYEVq/e0f1jgzuGwxa4geUdWNK7gB1OO4TGAK+nSP3pj8QGtQKYB95b1XjjN\njaIfVHyEh3VUem8R2x3WLZsfuW+aKt0hTvDf/9Q0S8elYWGNRuvIG83i+Qwh\nepOtJ9BIxWezfVM6A5MdUt0MlNwpf0/YdYRMzHnSgfxO7IodxG1IbyKNB70U\nJLhl\r\n=wb2p\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHcLHjXTt3DgETNeX43mgu/GUNudIel9Hqnrlr1xCgV+AiEAkVj0hFRXCFJIf7yN3+PCvMCIEzsK2ysfFUiOnoDrSuk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.48_1548657287463_0.6024017424140438"},"_hasShrinkwrap":false},"0.12.49-alpha.0-smartgroup":{"name":"teambition-sdk","version":"0.12.49-alpha.0-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.49-alpha.0-smartgroup","_nodeVersion":"8.11.4","_npmVersion":"6.6.0","dist":{"integrity":"sha512-9CTO+ogaGamQvjJmXqhpA+PPSo0S8aBKkTcaVAS772nGBWovc2oedojwuxgWO7tw+7hZYvsHeTwXhZD9GRX0dg==","shasum":"a0d95d25e2b809d708fbb006a066ede60f75c9b6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.49-alpha.0-smartgroup.tgz","fileCount":425,"unpackedSize":891972,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcTxtyCRA9TVsSAnZWagAAwYMQAIjMEMTEhnIIV67zmrMP\nOOn9S0Vy7oZhEqCV62nPDjyW+yEQednWOrtkPZx1NpkWqTstsv9oX3Rs2q4u\nvZwG9bcVr81Anh41eslJWrOKOwJpScmSM6K2hAU5GLhNCIngPFaB3f3+FWYj\nABX61Jn8m9LxZzcG23XNHKetJ084RGRR0PgmxOJYP9awMTQbSJvLObB4LQLC\n4hBg3WjT6XHhhCdNeX7Gy5pS8PdVf6T3sm6zvajHtggYUpAYIspOPmoGC8Im\noW4YP3ooNSXSWLAgs8K6I1Sb3BqkVUG5EqF27QM98ewE4cDPTd5sTYnud0BT\nbUTNnJsTyvKPTpH4BCtcxFiogDVaB+YsrFmTGw7Ss8Uo6o3Lzj7CsZ/lqH+Y\nKlJD4o4mJgjP0rUpbGeNGDnc31QurCnAVa+7njiq4i02AfrP1BKkSHmOQGjO\npg6rTiq3VzH94x/Wz8ZR+TNZrTy9x/cSzXq1XiMMckVRwZ0P5s2ClW9osZc+\ntWykIjab0fIfu9NslQ5NauD3WMZJxALgFNq1NGK1CftWYVsLjXCMpTdxKrZq\nFpu70Cip1nY5bBWPGhTssFw+DQzEoaKNrHTH7TjL1iXH80ksYhSbLUoXB4+/\neBJSdZ1S/F4yDmwXcsASH9O+B88B3q5uhEXqH1eoLd6ICXFsVNKR3oamPsDn\npgpG\r\n=Xovx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHaqWIgCYM0A3zlWyrlzfkQ1xHyzvbWE8jlhJxuNHayEAiA6rbTTvORBgd/8hoOdBC49v+uub9qTWijN83kDmRCD0A=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.49-alpha.0-smartgroup_1548688241868_0.4126311836963028"},"_hasShrinkwrap":false},"0.12.49-alpha.1-smartgroup":{"name":"teambition-sdk","version":"0.12.49-alpha.1-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.49-alpha.1-smartgroup","_nodeVersion":"8.11.4","_npmVersion":"6.6.0","dist":{"integrity":"sha512-DxO3ZJ0prvJJ2Vci4Flws4qYUMzgXESk6Io2xJT5nxhUXxcy8kDgbwNukeRgnCb+6QM8ELmyFThevLTVZUvCaA==","shasum":"daa4cd345a77a353f8532746aa90af0d9be34071","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.49-alpha.1-smartgroup.tgz","fileCount":425,"unpackedSize":892378,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcTxw1CRA9TVsSAnZWagAAq0UP/0lSIU4ZzD6d5BefIcM/\nZYYhzo2H8pTghcTbukUrogr8P8qK8kf5NDtPn4jhXMoNdPjFrvXdTrHBnIqZ\nLRv54MxNt5v+QHrxFw182Ceid/U5jpEQaaaC/K/qLx5rz3jwCtqeNDn8fdsS\nOwIl1JdFftDAPZK4nIkktj9M/X5bdt9EmnZz5sNrVBzAefJPRGjnLCyfMWHm\np+MVIFUigf5pSgXjnMwdYrVfKEYW15ksHSl07KYhbcUDRGB8Q1lSyyB6Sblt\nx4kIBIpE8ANAwOjhpc14RFPHLkjUZ/Mybp4zk8t9pPO4aIsSmnH1xhEMsVba\nuAzHdi3ERVVtx4vEhE+Zkrb72WAZr21TOOGxkePP625/R+ndw8jLTYOvzmiW\nARiR6d6cnPxU/3Zn2NAQYYtVdsjuZYVo3cCDL8W7bFscBcUvMl+yDl/ThZ8o\n3YIQ26oq9EwkVxNM3mmLfgvnRSpXuEBPoTvVH2EweeXXMzLz3ZNLrMtyPZ5X\nC7UmSgODdI9MfrbKGEAubWfp3DRvLIW3zQX5YtcpED2FuajPs6QorkwjzOEs\nkF9akTE+/q87LbDUexFzsZQhdzCh+ChGvtZQStH5IgBp7AC0pw++LOOQdfgD\nbUBLzS+lNtwVI9eAsqLCSMsBjQzh6NL79x3aUBxF/dzeI7O/FotFEzxBEgZh\ngzrb\r\n=4GLx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBvLGgWuiDsqKiwI5DO377fg5809Vi8LWC9tAvJys645AiAUYNHWjkbf3zmPdO4k57EpXEpy6eqGeQXnRtTHlq8Kqw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.49-alpha.1-smartgroup_1548688436477_0.746355796472417"},"_hasShrinkwrap":false},"0.12.49-alpha.2-cfcg":{"name":"teambition-sdk","version":"0.12.49-alpha.2-cfcg","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.49-alpha.2-cfcg","_nodeVersion":"8.11.4","_npmVersion":"6.6.0","dist":{"integrity":"sha512-sOlXGA5LSdKGgu1VzGyDudsRr/bHXcwoxn8h36SeBsa+rc92uAVGf/JOzp7uzyzuBfTljuQvcFWDvll8PYIQlw==","shasum":"7ccf7f87e979bbbc032ec5f6688480c59ecdac04","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.49-alpha.2-cfcg.tgz","fileCount":425,"unpackedSize":889887,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcUpm2CRA9TVsSAnZWagAAYZ4P/0KBGPvRmZMg8uyHttKE\neEpjd9Z2vif6O4A3Uio1WcAXkYCDXCCTpMJx9+3KLrv5V3KDNktazlqIZXBQ\n5JcN1XScVMyfk0p0reczzo25BDgzjHOpPm5DvYaUmJfhYUBM7igxpZ7h2pY9\n2YnqNTJh4da4a9szw5epbAMN8oCYFM/1zNoMODVZ/N9i9hq9oEFLpS00QXR8\njzBPyjDan00MW8MThkVxSKHmQq/7Y3YDVGsaCg1KXK/TpmoTrwmRbFTx56Ib\nnyWsDLkQgTIB0SYQyy3fkBMM/VJWmMAsrg9gWI5vUG8oi3LX+BljAyr28Ym3\ngciiVAIwHAMKN9xOEZiSyRSgMeTmPJifp12I5SG8JVyphNjoasW1dRhnoWSz\nq0ZgILihqJQ1U/4JHt4NUYBAZRVfebrxHXQcEUa47tyV3mPfgH8CJsIVEMqf\nPzMmTBTjCp0jGPQrzF0nAsj3TUdsmWDjy1WBrTDoKQwgqgenocfwRYEo4Rxf\n1lI64MvTacQ3wuA9oL1gm3mdNqzph4nBONG7XdlOjOOvaZyQMW+NkC6XXw9I\nmOUf3IVfkUQ5cFEyB0bb8xn9M4lG297PS/s/HcBOwrGltyKv+s8InkJypvVF\nnqrUvVFx7FqWadT6sLPFpe3pBw2+cpLSrr4kTqwwOTk8TYhxB3JboT12Dz7C\nZCF/\r\n=prsQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCAnuWSLrIAekyKBi7SNruHm2gmBPwj8pRAJLzKg5fKhAIhALCrf7JQOc79ym+J2bE3u30jeQcan13zYbnPCRe8Nhys"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.49-alpha.2-cfcg_1548917174341_0.15924939575845443"},"_hasShrinkwrap":false},"0.12.49":{"name":"teambition-sdk","version":"0.12.49","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.49","_npmVersion":"6.4.1","_nodeVersion":"8.15.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-9dNcJTTW2ZM+LZlVyhJAN0WnBi4fQs+8ZM9O9Ildtseh0LokOZsGu6IL/KZy+LrcS4sqovWj8s7ZUwmd2EE2qg==","shasum":"11a616c20cf20a4ac7961b0e8484813a68c31599","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.49.tgz","fileCount":425,"unpackedSize":893092,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcU6inCRA9TVsSAnZWagAAHdUQAIl9EmaLBixqyt/dhtc/\n6u6iZtVqIQXirLndyGV4d2rySV7M3+fBeIYwNMRUBzBaUDRC05qjmpxFJXTw\n0heFRwD6Q138x2D/2KyhmqX2E+2z3T6j6GMocHU/7M/ArGy1qJKaOI4yjjgM\n1Szo4gMtRFEGQ6Aqy3vv/YQ3udzKkAamPtlE4j1BH3gBXP4l03GfDZ0JXfhA\nPb2DcCCJv8RK7Oq+Ct2V7s/7kfMgQN4ET7wr8DR0xoUNJ7XfGmfHJQsXKNZL\nff+XdBEhXdwHl8HGydfU/Gw9dh8PSjDPGdXAlEvUdYrQ9pXI2IEqE9kALned\nrTYrXNAGjeTwuNd0bH8S0UDjh6bTop3nI9EMKZswPVD6HPKp0EO5yYX3grEf\n06dhmkx/AWGSNb24ypjtz4KhOObA4mzviLX8L1b3sEF3fjPh0kkwhDqdmFEY\ndQuxal5Cw+CPSZ9kgoIwMudVw9hNtBXjzLZZdE8bE5FmfJdaiAhT1Qmv2GEQ\nGc+cRSc3kHxeYrrZTqb3Nfkc9S+ZMtH1OayoXsHzb0/1gDDqug8rV5oaovBd\n8r8K2j/qF6vqpfyt8J0192Y/K3wZZWwjSM5K1mW8sZ1H4lXbcqcLpTM3TwIR\nYD2hyuN/wbe1/sVRG9zdQxAzFPvZkYoJcKiFk9Z/AqGopGquRBFpt+rMybXk\npdfg\r\n=omkB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEQNHzmjO1hiBUoJ4RytDmWc7OrdwRpLcaQpIh3LbtzPAiEAjaePvoY6cpz6UzHqH8LeshKKday0jlZJgOeES4YR7sI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.49_1548986534100_0.4923904552895566"},"_hasShrinkwrap":false},"0.12.50-alpha.0-pagepost":{"name":"teambition-sdk","version":"0.12.50-alpha.0-pagepost","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.50-alpha.0-pagepost","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-U+iE4+RwvkMy1I+NhZxyG/b7Lr8SZ4ABiheTgyZq5SHZTjB/TCAQIIdnNkaku9NZEkUBUXeaOdiTIljMu4z1NQ==","shasum":"760421dce1ad7ca62446347b6d6a52563d192f80","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.50-alpha.0-pagepost.tgz","fileCount":425,"unpackedSize":893794,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcU+GOCRA9TVsSAnZWagAAbboQAIWwyDri2AkJvNdaZA72\nkq4hc36IXoFK6/ex88z6D2s5Ifpb+FQ+q1P/bkF9CUYmiHpbE6yuLmZQo8hT\nlDI/8KAPyqo3TpGM+T3ioMWyFoH7J2aK3h4BcxYSpWqsvLvCNwN5VkrKlqz1\nUyaKR6Ed9yYwfK0CBPaf10zx9QYAQJLSuDLRZFta9BEvcvjuyNzEgQ6eIGpi\nszhVFy8WW2VB8KGMYhL6JQGMev0WQAS/OvRbfmVC3CYtVtVgCcE+bcB/xGr/\nDbcf31dXaJxm5WZxL2v/j72TUj8qCAoMaWUtdHigWd8t2Sus1gAi1+mFlL2U\nDFH4PGs9JThu+DWQAKMtKDo5/gKTdJX8hkc6LhRk3gGuIzN8P6ptQSFLsWdC\n9jdoamIt/NxS8Z5hpaeLjZA8lX0PCvHg4qwreCTX67QF0EGMhXN2zArT+V1D\n1xtkmCdfrIvlJ3khNTLdmoF0IqewbDKbxA9sqTxe/RGm8mIjc+avmgapBbjh\n1i/lKIBZlrx8Ub6pbbKU1Vz9iNXQzebbiDpKPI6PkO7Givs0ULPl+xKo52P5\nKvjtPbTNAHd/kT/HrZqDYTJ7ekDf/Sqj9uyyTQvDQfRJ8RNRZrzQg/x2pg17\nnQ1IjXVAL4waSker2xEcigtyHlSHzC+Flou8PsFZ3qRQ3TVB9l1jEMVPRmAK\nh8up\r\n=muPx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDPPXF85Yixl/wEZYdfSL6W4202juUAvKqc4ZsoRFFxGgIhAJSjm1HEuaZ7oiSemOYy83MPhP9cLWWTG4yNEg74jqeO"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.50-alpha.0-pagepost_1549001101338_0.23049000198925662"},"_hasShrinkwrap":false},"0.12.50-alpha.1-cflock":{"name":"teambition-sdk","version":"0.12.50-alpha.1-cflock","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.50-alpha.1-cflock","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-LA7ZHzWvu6xxn3Iuz4/MuGUuGCLTXwqq3PfyIXT7o8kSa0z9jUWbhVH9JwHF5/V/lB8tuIk+c/2nQErZ3LpVxA==","shasum":"821b85c8c66fdf16dc2d30372038d75dc3f2303a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.50-alpha.1-cflock.tgz","fileCount":425,"unpackedSize":895393,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcU+JbCRA9TVsSAnZWagAA8KQQAJhQ9zwj1Ti8QE0U7XnK\nZcZC+hmhJwl26/QZDGWGbbxyU7QGWqgWBizsjKEIcpAhRPh+819SIUTPk8rS\n0ZIIu8uTLEFsAEJFNUFy9mMY3TIOA0YEwuytolt4L8pNTB7Sm9cMPdB9gIYs\n7ksorQktpJYhRipO93DmjofVakCxbSx7ahtQnhEjUzIA+qu9UruAZq+k7DRZ\nW636xg4t5rbATbz5wSFi2yuCPFb7B8n/7WN1Dm9FkxKtJ3gP9mBVVELCITf2\npPMHS19gjBBdNb+ezJ4+VNZ+6uTZ5oDoEH0kI+jykwsjhtF2XiUnE+I7uSt3\n+bLV8N6/WaYKvN0Gok+lrNE5gaSMisFK5POItNLav9FnkwlZPTmT6K8ef+8t\n8s010fUo68tYKVXXzgXQrnuzBa0/S3nhpmrMFRHSanT8jXQc1QtDCacP3Ji0\noMz0X1LTpA3Ibbv1+vV/7T6FcLp1LsK7WmnGIEwMzwxWbrM6TQ67DzfHamKg\nYxpNU4eD1Boh5LSEMEq+HFmPnU0nO8TeynO8b7wC9i/ZHu4Kyfpxf0XKCHo0\njcw7MMhw6Dr4c+DMix+1+1g+T6PzPKBOWVXCQt6QqmUfWk1fyT9ruC3cmtho\ne4C6oUeN4ARfqk7Q0unpp5IYuGsYxcHKReFXP3HQIsQna/pCBdkGbAMXAYs4\nm3IP\r\n=cQIT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEthLTHXQeGTjPZ6ZYST6cc4hii28R2HT15WERvAG7YyAiB4t5sDdfusa2ZjmFKJonXT+9C+7FURSgYHqZR4G9Yp8A=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.50-alpha.1-cflock_1549001307244_0.8854943484885482"},"_hasShrinkwrap":false},"0.12.50-alpha.2-cflock":{"name":"teambition-sdk","version":"0.12.50-alpha.2-cflock","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.50-alpha.2-cflock","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-MFdxCx80uXgeKGInbe5hJZtGAKf2XrYMTLxIIqNO3E1NjdmC/yKIrvy7txSpb6PaUDTpppbzlbzgB05GCe7FRA==","shasum":"cc033e326c0e63e9efc4c8b5ef6ea8567f95b6c9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.50-alpha.2-cflock.tgz","fileCount":425,"unpackedSize":896261,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcU/6sCRA9TVsSAnZWagAAUQwP/R1uoi6XT0NbWsVmZQBE\nN+eIW8a95bAM+ZXXtqTSJ4AXyYFn2OgpFBw9QV654FxbluOoGlZrWunZruc0\nKxJDPXgOJRBIZxt2X1992ozuXvtzfBEgoT2fG4JqQ8hYa5yf86pB+23JLwfO\nRObYwy2NVODzUapojVVz3eL/eZe66N4t+h2HCy3p0PVcgBfdWvTqfk7zmh8g\nyW+og9e9oxn0eDPDzryBpkkDAAaab3R7ReSR3n3b4C8zxNBasd89Uo2IDHf8\nhg3HM1mDTGQIwwzl7N0hZ5SwMxUPSr5kmcIlHOId+YQqqTRVVdaP4p3Bk6rx\nQAL+lTpY8GuFtB8xPsZbc07AVFA4KiULWEKEvJB5qVet/sTDBUTKfEqZbBe4\ntgblJBleLvTuBgM1bPGAUaLUVjxAx5UNbTDfGl8l4GP0p+m1W2adrE58TMMK\nEFSTEobESCS7sanIYkST+ak7Wy3hmrmKQLKcomruQiw4xhRwZyb6UzxwiM9I\n3EXWMwEnbm80XDzqz+qc6VeOR6R1zBzwyEhPQWX6CcqeUdmHgm5fz0scrCt+\n+jemoK6//C0uTYd14xE6LXFFaO23wF7W8iQcLxcqUZP724llB8313AGOU1mJ\nYANu0qLIW6o/jbHX5FkcbeHd/BwXL6J6kZAyqLhIWqsN4Gp9xW7ggoBM2+0e\nhQ0y\r\n=dcLA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDLALwmov5Ui9UBLr6shIKBJRj/5J2F39Jv3y+qzvA/9gIhAKCe7UqllbwK60M+SHcjMOdNWvftoG/6s3zRbK8AHpU4"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.50-alpha.2-cflock_1549008555627_0.9641781469745716"},"_hasShrinkwrap":false},"0.12.50-alpha.3-cflock":{"name":"teambition-sdk","version":"0.12.50-alpha.3-cflock","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.50-alpha.3-cflock","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-Qn884cAhVGzs8whx4HnEoYLJZ2CXViz7DbPjm18LQj8FFRtKGDaGZbCxRDAcxCYx7Q5RNR9sRNDVSlmVRxtpAQ==","shasum":"6fc351370e2bcf06990dffc8763fa897fdb67547","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.50-alpha.3-cflock.tgz","fileCount":428,"unpackedSize":900804,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcVB+QCRA9TVsSAnZWagAAjYAP/3k4ijgylE+9Ix1yI127\nCitTlWxWWCjwvJgpGwcNKGQcNOk2N0Q5Hxn/N//d1VXBaKTuOYdi5iXFKqQu\nBchdqwCrFHzMybkrvcR4GZS8KmGOYqfe35KpvxDQdAH4Ytv/cSBoGdCpq93C\n09//PR/Ysn91YeSjZbG1qh9IUXJ5RopuDjVmxoeZxbHma4dmqLCxGbE+QWuZ\nn4APafdlyREoJk4ZSxdgO0FLFCXxV1iM2ZtG2Ks4OvsFH98YyCguRKa0HeBw\nsW7b4E/AUs8IEsmu6+iGLL2mdAgNpXGDWTcObG589Gbeia/I/IlUnVHzhH0g\nStMYfYVpsILyuuGNeVUxq+IOHELBcMIW83LykGdKOK6haVor2JRjmRUh3mYH\nPpxaiDCsSLite/M4cBbrgX807F14OGjCfj2oqBMhZUxQjLKroeHsFytftaJc\n88gLXnA+q1H4vqbhpqWjVtiEbkbjg/sEtuRrQYeLscV2U27CKi5JsMuEKugx\nTinis+WdU4mjEiR4utN+QFHIx4jHmjNFK8yZkYsnm+CHVoceLDSeZ7gNUOSu\nbeciY5Ihebc8d5Ulm3WAuePkY6G+WPHQ4/cHq8RgW3kq89BDqLggW85bXg52\nyDdyw1+4t/q5aRHGnBf3qw4CUuipwuhhc9acVVIcOdEhPgFCmgBWrcUrun7l\nu8rA\r\n=KVDw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIECSaB69cCFdo+VvAdySVQ7N3gs+appgGHir4dVXceqMAiEAqHiUNdyCHG29SRGkNLituxfTq7JBNsFBJ0Z1bHbwcDg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.50-alpha.3-cflock_1549016975240_0.21766960640212862"},"_hasShrinkwrap":false},"0.12.50-alpha.4-cgcf":{"name":"teambition-sdk","version":"0.12.50-alpha.4-cgcf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.50-alpha.4-cgcf","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-nYRuGOHUj9B6TIu+WweCONetQWL/p1RB/TTbyGJbpDCfS41ojxmSqDSzHipU3Zzrd0HVOkD92X4LdH9aXuHOUQ==","shasum":"76a0d2bdecb5e2c0cd70b992ea5cc68bf530445a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.50-alpha.4-cgcf.tgz","fileCount":425,"unpackedSize":893939,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcVCoMCRA9TVsSAnZWagAA3xQP/jV7ItTVt9I6o86ZFVGz\nqbUP/MdKYdRoAGmlVLz3V4d5CAkn9yGIsem6xRLO2WKc+zdRR2goNiCIAR2E\nwyB4Z+1huZHA3+JzqbwolNMRsUPzcqmdXaCM5i4WPt6x2hcKXGwQ3cONZaVd\nfIxQrMo8H18zYbM2NrLEDqaEKyJzIiMWC2JpGPdOGw6uopPj4IsgMyzhtAuD\nS7O8i6w5JgpnkE1kqQs6z1XFnvBqWh4Toua/mJEaaPIkTTOKlvcKvk6EZwuE\n6EKNDdZvPAt1PUtN5jYJFpoeqjm4mNO5IoTFZXbCC0uVC+UBuogtduVxsMWx\nSXUVbTfRu6GLuDZIqaBqMloI+iAzXK9zhRBa00LpekSQqj3WuqKSWZ7fGELi\nmugfY8/YBSW7sSBVuT1k0qoQeh5X8XxH8k8JVrllTACJsKLaDyXej+I3uPvH\nKyqdWkg/+K+sxYgpkUpm59WR3745+umFVjlEprLiuCX5jQSVMubNgEFJs8PI\n+taB8SV6ZFs6PhFQcr30Ypiti3lhP/6GOgbHwUfmkvhdEw/Ninc4ubj1cqAv\n1qMZcn7yM2TTD3FPx7SWhOzrEUirif2jUboOrPl2r32fgovHX5b4sxGRTvhh\n0s22sxUlNLDnS1ga9bUTMjm9eo1Za9gcJzt1IHtOOkGi8OOJKCRXnjvUuOkK\nyTFT\r\n=b4pZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD5e4XYIPTkCfcL4rMHzjiKZvwqSBl/BWMUir4YdMoKJgIhAPH3RWzEObD9G5rMkqvld9Qo7tvpaGsPn3+noL/MU8eZ"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.50-alpha.4-cgcf_1549019660288_0.042936298042594245"},"_hasShrinkwrap":false},"0.12.50-alpha.4-cflock":{"name":"teambition-sdk","version":"0.12.50-alpha.4-cflock","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.50-alpha.4-cflock","_npmVersion":"5.10.0","_nodeVersion":"8.12.0","_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"dist":{"integrity":"sha512-LJmYfYKwpsL9s+4eLI+H0DVKFM/0B7QLIIftPKdfHDspH1BrAv+Tj49BiwUm2qxpS/VNPWgC1buTTXKDh0grLg==","shasum":"bcb9ef9c0a0cbed3738876db1763b1e18462dbcd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.50-alpha.4-cflock.tgz","fileCount":428,"unpackedSize":901328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcVDABCRA9TVsSAnZWagAACrMP/1+ppJdYrwHe6NIemYpm\nJ0SpCnBTNUUXi9cD8RMT9fwC8EAJfuPfe5Uz+EMia1dwc2FgRYorCaDbRDux\nBHvjRW3+zMiM5+7+psI79BwRgvMLMQ83hv9iCBEsrxQJd9P+Vgund5vWS7iI\nGScFFPuruc9jZxOJDn250jgAvWjjsCMLPoJS4GouOg9PCe+C04xkSM9LnBnM\nfeNBBavW9qKjJvRrZavn75BOKJK9G8FMPlHN349HM1tJaKxDRXgfJMSmil8+\nbU5aWS0Qlp133XzngnKp0a9KLF3JYJzVNzIIJ/HoQzZsIuK2dwlDXFVPzWYq\n6rvFnCJkIX04PTob7dDQ/Vq6GcSFG4YpaPuNBB/5yPK8obHNkkWCvaYoJkKw\nZwZe+w2qYBKbwlvPMPmmVPpoC7h/H7QPPn82O6N62QPjGgTKk1TAclfapcAM\n0j5X76jGtCAfJKsuXQ8CP6oYoMJj4bmS6TzW7rYCeBhnGTVPWZjSTyRPhcv6\nz5iROHyk+tavFSOJKf4pnZYDHXfo3bEVkV9TMXfHar/siTKG7zG3J9Ibo55j\nomEoSbQB0SQUtYGS6xs8vLOTsD1Su/+6Wi4yZyhv66nhzIv/8tFOHl/FdVP5\nVHdHzaWGf697R2OF45g27ER2V6z/ydJXT5/o9QfZihjiffRU6WLzVus4E6+0\nWs27\r\n=ZiCI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDwo5YMsHAgF8uEQmv1jHwHzdmr8jYJSiu6amIK8plUxwIhAI3nwVFy1sgy7ej9OFZ79XDegnxPZCq2wgF6hI14fcvW"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.50-alpha.4-cflock_1549021184489_0.6119831685086525"},"_hasShrinkwrap":false},"0.6.29":{"name":"teambition-sdk","version":"0.6.29","description":"Front-End SDK for Teambition","main":"dist/cjs/app.js","jsnext:main":"dist/es6/app.js","typings":"dist/cjs/app.d.ts","scripts":{"version":"ts-node tools/tasks/version.ts && git add .","test":"npm run lint && npm run cover","e2e":"mocha-phantomjs test/e2e/index.html","build_cjs":"rm -rf dist/cjs && tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","watch_cjs":"tsc src/app.ts -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_es6":"rm -rf dist/es6 && tsc src/app.ts -m es2015 --outDir dist/es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --noEmitHelpers --importHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_test":"rm -rf spec-js && tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_e2e":"rm -rf .tmp/e2e && tsc ./test/e2e/main.ts  -m es2015 --outDir .tmp/e2e --sourcemap --inlineSources  --target ES5 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.e2e.ts","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.socket.ts","check_circular_dependencies":"madge ./dist/cjs --circular","watch":"npm run watch_test & ts-node ./tools/tasks/test.ts","watch_test":"tsc test/unit/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,mocha,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom -w","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node ./tools/tasks/bundle.sdk.ts","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015 --outDir dist/mock-es6 --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom && ts-node ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --noImplicitAny --noImplicitReturns --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom","build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_socket","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/unit/**/*.ts","cover":"npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/unit/app.js","publish_all":"npm run build_all && npm publish --tag legacy && ts-node ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ --tag legacy && npm publish .tmp/socket/ --tag legacy"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"core-js":"^2.4.1","rxjs":"5","snapper-consumer":"^1.3.2","tslib":"^1.5.0"},"dependencies":{"isomorphic-fetch":"^2.2.1","rrule":"github:teambition/rrule#v2.2.4","snapper-consumer":"^1.3.2"},"devDependencies":{"@types/chai":"^3.4.34","@types/mocha":"^2.2.33","@types/node":"^9.6.6","@types/sinon":"^1.16.34","@types/sinon-chai":"^2.7.27","atob":"^2.1.1","chai":"^3.4.1","core-js":"^2.4.1","coveralls":"^2.11.15","engine.io-client":"^2.0.0","fetch-mock":"^5.8.1","google-closure-compiler-js":"^20161201.0.1","jsonrpc-lite":"^1.2.1","madge":"^1.5.0","moment":"^2.16.0","node-watch":"^0.4.1","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-alias":"^1.2.0","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rxjs":"5","sinon":"^1.17.7","sinon-chai":"^2.8.0","snapper-consumer":"^1.3.2","tman":"^1.6.0","ts-node":"^6.0.0","tslib":"^1.9.0","tslint":"^5.9.1","typescript":"^2.8.3","whatwg-fetch":"^2.0.0"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/master.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/master)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=master)](https://coveralls.io/github/teambition/teambition-sdk?branch=master)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport { TasksAPI } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.TaskAPI.get(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  constructor(\n    private TasksAPI: TasksAPI\n  ) { }\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport { PermissionAPI, TasksAPI, ProjectAPI } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.TaskAPI.get(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => this.ProjectAPI.get(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return this.PermissionAPI.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  constructor(\n    private TasksAPI: TasksAPI,\n    private PermissionAPI: PermissionAPI\n  ) { }\n}\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n","readmeFilename":"README.md","gitHead":"72f7f7eb12cf67ca77d8d8da866410813a865c89","_id":"teambition-sdk@0.6.29","_npmVersion":"6.4.1","_nodeVersion":"10.15.1","_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"dist":{"integrity":"sha512-+xRDIQhfulOS85dv16MyyWiRIwsNtvirCjGNFro4ZZg2dcQxFcr0JmiCd+ZrSsvdKSOrmi8O33R9PHsp8ggEQw==","shasum":"5e7f44435fcb45039a87a9f37950ddb471568efb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.6.29.tgz","fileCount":1217,"unpackedSize":4570459,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcYnpQCRA9TVsSAnZWagAAL6gP/30z2hZax7sT+54AwHay\nS5dZFi/cINpasq41fi8RA36Mm+76XWA+MFP7bqm13PI7nurcAoY+9lxpmWOB\nvl+2F607GQSxakA0KYdff9C74puOtRl9DFoVAaAWXuL7kamb/qR8i/MWB+b2\nmaVHpZDCvUU9xwzCHikhVpkfL6iJsKzvvuQzhKoBSqVlI6WrKZrJpqMYmNAu\n8pR786y3RDCM+L7vriaEenHNnp4oO/TcN79KQrKUa4i4xc0WM5yCncDpwPtg\nL1KUbFxXZVktlXALup47LhatolztqT2JGlqPxMY6+00Vs8qVLGrhzfJpiozY\n5Y1MluJpEqm5iIfNNciR2uQGReF1+ecLsuWSoYUm7TNza7bw6Qot7j7gvLmU\nxoFfGVP79GxxhMoXn589XTJVfC+O40nXdNTPprHcH7p9n9eGwzBZcs8h96ww\nYuM0az7ErZIiYhGTlrU2WASCV3jaKzwrpnWEGL24rP+KFkyY36PWjbzi1uYd\ncCbMDyYuNixGTAEAFEwitC490k0QWi/3niBA2WavmNxmHS9IHEQwhwkPE4+7\nGKfzrjciXpKdIuu4Bi9YosawBiTlcksb8VMEoIVgKRrL0222cBXF2YsudUDT\nZHCkc3O0zBFyAeAmyUphTXJsvXhxvHhxbx0cF376WI3Qta+mhe54Kxh5z8rP\nqMAb\r\n=oWfx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF72YZ5HcSUNbB6gkBtcZhlbsIzmPZk9GZwYRFDME00eAiEAuKDdhYIQy1mo7GmNSw2aoFMqE6867kf8aFycalA6xcg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.6.29_1549957711388_0.8712470633219516"},"_hasShrinkwrap":false},"0.12.50-alpha.5-cfsingle":{"name":"teambition-sdk","version":"0.12.50-alpha.5-cfsingle","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.50-alpha.5-cfsingle","_npmVersion":"6.5.0","_nodeVersion":"8.14.0","_npmUser":{"name":"coldfannn","email":"xiaoqiaoqiao520@gmail.com"},"dist":{"integrity":"sha512-6ZbMqwPKKrc7QUeZn51MB/yzEBJ/sBpovmIFg3AGFbgwGiwYrSR6dfVhquMiCoq+g6S3mKIuBlkJxvCZdmVeWA==","shasum":"dbd645e2f1fd219e2f040b571a1f07150f7595d7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.50-alpha.5-cfsingle.tgz","fileCount":425,"unpackedSize":893357,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcY/U5CRA9TVsSAnZWagAA8nEP+wezK/PjTEkhRaYwRPqq\ncuXEUYwlECx5exgeVwSmqUa7MQI1ExKYdCRpqklUVe8FmrCYE4U66697Iu07\nM1iIgnyEcf/rY5LWeNV4OTwu6rpBlRnVYydTzRnHV5W/ZGIxfGbM5b/DrrJz\nErKIZNVVJpY6s6V/QT7HOWJtSmhP/7hwvF/i0zkBpA/UtiXA65tTnqAhendI\nbAu0uaeKmDgUR5dXbfx/RvGI/DxB446K3V8nYhdgiUZ1KyDO+g22EegWaeVl\n24tF7xV1qbcUBf6UuJqnPiVFu3emq2ZptI9V6324HBjfhR0tKZ/DzHZlH1MM\nxSR5M8YMY6p+bZazGF4/FuuA/nvT5yaSeSKVVsEs9KDm2hgV9w7l21JveOhu\nX3ISeqjC0s7dwGV9hO2cQaWdg8M4zATphgBMWGGFYTSG4HFL+ONT85PJbjl3\nLkvaKSdADCcqdaYX5JPSmGQyDidUKlVQ9/dsQRbChkP3xufuXcZUVWP8ByeR\nQB+o5uv8Red18NRsU+1nYWZ7xCTyD4IW3GcY0QVObocSF3wbIHtnbKbDcNFs\now8qZ4ePt/qqehQGRb3fSLayZ9/veFSkF0YD1kwVeVpWokwKL+YSd0zK4bOG\nWLTXiarBk6ItvGSXOGBCGhnsFIt5iYhbUBmHGkyn+99nnughR/8uiai0Er1q\nnad3\r\n=6+d6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDkhOEFDSpFPwdx4J/3rBY+bHjayaMzu+1e2h9sCRXzIQIgXdhI7rpX1uUwZGzdIeGb6Fthvjw3pnph1bV35cJsVbQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.50-alpha.5-cfsingle_1550054713065_0.5014601212307057"},"_hasShrinkwrap":false},"0.12.50-alpha.6-cfsingle":{"name":"teambition-sdk","version":"0.12.50-alpha.6-cfsingle","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.50-alpha.6-cfsingle","_npmVersion":"6.5.0","_nodeVersion":"8.14.0","_npmUser":{"name":"coldfannn","email":"xiaoqiaoqiao520@gmail.com"},"dist":{"integrity":"sha512-6hEYmyygiCDkHNH0p8BQioa+bJcQV4hl0nY0Xcju4VFRrxW9FhRzM5526re2QiXR+6hwh3nTrgTCL+fmhZ1ELw==","shasum":"fa08919d0ea9753656bafbc4d80afeff2339221b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.50-alpha.6-cfsingle.tgz","fileCount":425,"unpackedSize":893359,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcY/0fCRA9TVsSAnZWagAAfRcP/37+MMV0r8MRmt3QOVlr\nGTbcvLla5qRFb4HnXGHd3VmG0N31o266M/HUl8nEg0+26uGYhdfuz54kd9Qo\n3O0AeVkIDuk9jZtasJnmyQ1YJBcSPF+x1DmfGOhfM0MZRxqVYxvtqHZLUBs0\nB5nfjeBgojy+6Z8S63oOEABneBqZzpobl3x6+8NaRPDsZr+xkoobQROVA3y/\noGjDFOIsLjZVDuAsFsCJ98aKIOnUShVmvOZi5LbfYznkLlI3jyIwiWaJ6rt+\nwIE4/ulT1dgFi+rbRnbbqfbuVLAJVcF/fJ/cHcR6qjHZq/SCUxx0GjJKU2hT\n9+469/4d6gnCN6mcMf9cci11TRBwQhlwtw67xxUhxabcRMLUp9fS7OxnvLMv\nMHE5o/ZA7TjGtmaIdm+3al9lLKgyAfhYLr3cN0REclD4IwbQkmg1Y1hp+WW3\nPK1B8bXCrre9k/K/+X1uS2bchTxAW+9b8n38WgskErxc8ieBq3XETw78gyId\nEkSzSTPn/ZGq4gIUnQws8ZE7tRCmKS8i5knitUVqMC0OaOpic75hrE5nNOV6\n44Yz2VIw/0YNrdjt7MbcBSJ1f0+ffgNvwOtMIVDGEuDssRVWzAZzyT7zDUfE\nnBOLNsB3CXV/V/7lYJwb0Y7Ym8MrsZBbRgeYhhs/VQZJ19kvb+zDJlP9lgFI\nTFHJ\r\n=q+/R\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEaeBF0G6oL+ADtWHqCzJxH/MQK0vlZTgxSRiizx6IybAiAgCRSsmFOjyjQQUKKtC0bV4xkRDYobhNy5ZnZ6rQ5I1g=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.50-alpha.6-cfsingle_1550056734942_0.07328944756838274"},"_hasShrinkwrap":false},"0.12.50":{"name":"teambition-sdk","version":"0.12.50","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.50","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-9dTlch5fI8G1vKea0M1jLszFL30IeaLwnVfi16wvtMQz/AMz2MgWgh0BgXvreXfRStQSSPIYvtQluW7pVkdPVQ==","shasum":"a54bd03ec4e9cf3c1994940b826a18c7984d6fbf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.50.tgz","fileCount":425,"unpackedSize":893592,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcZNN+CRA9TVsSAnZWagAAPK8P/jOOw9y84/UoDFbZS6y4\nqPSLpPEMQFPRz20ZD/1Ag5glyre0yRmiV8axIDwF8VqkYcgrbFVLRIxKQVfJ\nxjYYP04jFtTOC25isuY+UOJcyLLXfWuhxUnYJj2AC8LrYhbudFGtG4vQj694\nINTpa0dcdcFzMOGnROR3pgwiTLjn9lAdU1leGgF5wpqdQCU7QrgzGUN/8h+F\ntzkRoH7/mgIlna9ij7zyiAGIsv7fetNNZ1QJyk33fIrFUH1r3oI0exWV3MJV\n+SqOfGupkBTRGtDTJK8E63UQFO5nNEqK/3/0zCiOYUDKHDPzDZdUKXOSJok2\niY62wkLS53xe1TR2vclTmJO2mZWpgKY9ul0xvp8H9eBVAoMzvSny8yn3NTPN\nhyeW+MheIW1T+PcihhVRl5JemWJPBEXmls4Me+Uv+sVF1MJzyiia0dfBBhnh\nhOIPc9FP4rcTKer9waYI/MIT6Tqj9k7Q+0kb3XYJ52ohtCClhi8uJlPraxZr\nZ7nVLAFB65IpkZF9bKOsZ+wsuY93VRTfTPxhunMFcROubGEOUvLXvJS5PcaT\nywAaImTqYPWR/rfKRxmwct7q88lnlBojAR1oqkOL0/tm/nCEUdn3uvqPJK5U\nZMtN6tinpsBVILSMFpmXqLY4YLkoUt+xcemFWg8PR3KPhgi0tcgcaD9rlqoO\nZcgI\r\n=I2Cl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEfsCrINpsKwj48+1ts9RJhG2Bt9Gh29IQjjgCTmPmokAiBX7i6HkclVt6/8Gv+HBY05Ce65OFhbOzAEu4BJvTVxTQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.50_1550111613938_0.6420762958781165"},"_hasShrinkwrap":false},"0.12.50-alpha.7-cflock":{"name":"teambition-sdk","version":"0.12.50-alpha.7-cflock","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.50-alpha.7-cflock","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-nlrVm88fdEh9+wTkCqq7so9jzcBBYG2bP84BMbOpZpvlyLhzfVgsB5QkcNrhcDvihHeREnnaoX9+8DUDZwgcAA==","shasum":"c3d8e3c2a2cb8b7845148e487459a3708826bb0c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.50-alpha.7-cflock.tgz","fileCount":428,"unpackedSize":902820,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcZPtQCRA9TVsSAnZWagAA7KoQAIS70fi2M0ZFg53zMP4b\neJUXiTLkEVJ1llU7Npwowd5W4Z7Ryopu+Aq1JetmnaBoy5kl4gH3KLQmp8cK\nAr6+ybXWe2lX3IEBzYmKeU+Q69iRE7SiKUjCk2KfIoLMeO6wkT0kum3Ac9cW\npwvpj2Cck3NTHXU7GzPxv/pLvioJjAmL/VZ9IL/cjnSZ5NHA59aKv6xM1kLy\niyX8KwZGL+o67bdkmNjxVIGCdsKXSrkc2o6vXLyM/GIZOoAWwEncQ99kI6be\nUDDs68OhYpJCyKAyNCY1UQSoV02mFyLXuzn4spSgmoCFj2kw8t6G7IPjPul+\nn6hmWaBNcFuBqV838X37QwqBCnUcu2kgASbcqh+w4b/iK2NC1bPP00d4UsCu\nGXk5OvoWN4+OiiMF6fWJ6HUJAY1rpqOdeqAw3BIzUeTa/7edvGaU3n6t584G\n1KTqY7LO4TdFqHmn6oQdxAvX+mIeAQxTkUWcMUiAdR+s9kZEDR4+izUnIxxp\nA207TuYaNW+B7v6enU8aOLwXRqrv8azjAS3MIDuotA2HrUaF06YjtYmocbyf\nlEq1L9BP3tRovT78eZ0Hpkc8YE402movETZ3UB8XLlIq2qJ/8HYZrpl0nK2S\nVc1aHt4qar9miOHFdkoN+aUIPF0t1n6GkuFdNgP8VAaUMMF93rFNh7ARiWIE\n+DRF\r\n=QAEe\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCpi6YU3KVAicGroiAjdxW9GsxYyLgz+dEg0gQPeE8LIgIhAOyMKNUF1ADs2Tzgqtd09ohcN2BXCxUSw4j49rt0MrMz"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.50-alpha.7-cflock_1550121807970_0.43887997651092103"},"_hasShrinkwrap":false},"0.12.50-alpha.8-cflock":{"name":"teambition-sdk","version":"0.12.50-alpha.8-cflock","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.50-alpha.8-cflock","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-24ivz66lrvTuK5KGQnUHf3n4yL0ep5Gun+NDOpWbx7LstXAJAcWN2N/7ccMvrDCjNIHfKSby63MWgX0KM94rCg==","shasum":"a385d2f25d79e605bc35a8be43db7d20c1684bd8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.50-alpha.8-cflock.tgz","fileCount":428,"unpackedSize":902820,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcZRFUCRA9TVsSAnZWagAAreQP/1Z37LhKoRU88/MYoCp3\n8OOqGQ9qzg5DgapTNU6x+BWkZdUoYOyuiLaWQDuncw6VZUmby79tN5L9n1rY\nyuA2j9fqUcjbL9F0UEK1PlWr1Z4zoWmBiB8VAcrtsrvOa60+mcHTE5r+an40\nGJAf/5IRKcurzpN6hqCdFuzOpGJJtZdkzZGciaF51CXe25XMhR+oY5j2f+fX\n8Q42N4R0QiuU5pZnSMebkDOK/6lSuvJEo8M2PKih5p4BWcx90tzc686r56Fb\nG+9y/VTrL2qYZG6Bm7FFUPtYrvgClaMk0uVx5BUDkhW7yLzbqd1OtrAU1iiy\nS4rFA6ns352W4Nt0ggc/gOxTTfVxyyUEcSZq0FPeCKSSTmClkNkMTYKlfmt+\n0vpy4/Zva3U+lgII0M8HryqDOMmytYyRqTFgJlBiEII/6cZULNWI5eKWtODz\nVV8LFwfpOEHwZxOdcvf8smov2yFQtDyyWqkS2Z0I7ZH1CBdv6+qyH/rr/Ql5\ntGijDZkv9cPsSkZkc0iVed0goNtgLiwqpdfhM4S9SFkITj6hUnId1aIj3kPr\nm0OyXv5vbiMcYjRKO0YCWt8VEd32+oFzZwPvnShuAoFgomJazjBRMbF/4pgO\n44Pqfaf9QVX5SvpdE47dPlawrnMwWILMj5EU7AqmqRgZ9UseqFo3YrxnfwGd\nfV9h\r\n=JMfS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICQSaj7FtaCetD1/BuD8rGdd6rTSEfHX+dcNdxQ3IUvtAiEAyS+5UU++tt+lDBC56EEmHzbAwCZ6jvOO56T72mizERA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.50-alpha.8-cflock_1550127443894_0.28872754850906013"},"_hasShrinkwrap":false},"0.12.51-alpha.0-idb":{"name":"teambition-sdk","version":"0.12.51-alpha.0-idb","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.51-alpha.0-idb","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-NBdIoYKHIlCPqwoF/Q3EiUnZYHUdWchB6QMV0fvkbt8YWnzG83AYwm9b2VOXPyXAXO6Fy1hikXIAt8Ihg/G0Qw==","shasum":"8ed3fed3b89f4d53e5e236f3773c91ecc18dcda8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.51-alpha.0-idb.tgz","fileCount":428,"unpackedSize":890559,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcZUuRCRA9TVsSAnZWagAA9X4QAIP4ZblIrddaJndssUyY\nO0xbM7NnRSCZsWFO7D9W/2ILGQ5i+LSpC6sTgaPZtiJhrVsAc7mo2jTkx+gu\nUun0ZJQBzNMBEKt1hDdqjqgmbJkh2Yym4TVOnRI6s+hqC8JfDBnNW7LFc52c\nEGdwE/Y22kzAMvGxHiE/1jEYOUlvy73chaAOAeNo/fp7WaPtK9bAsGrhfpkk\nfm1l6g7kW5ZnVQ2wMbUGNEDIJ7takag7R0rPKuwjUserGAib9yY1D7HmViWA\nlaf7BjZNnSYdnRvk0y8jIwgT3DbHFOmEem6jUrpyNap1i5ffNj+zRNDJDTX/\nsu+/iy6e7cl4+YZlecn1N8hdejqwmY/9Cr7oSBtCxAonklIBU3ucvjc8MN7u\nxFp/jFfCqHSWUOSKzDaF+vpdMyOFvomVtRJzqxwBm2yf2wMHdJboGEJBn8ge\nHogvNFU/X2I4vFmBbORnS1iSoBJIQ7SPyfK66llkFnwfee5akHDEnZf8AxET\nykbjCQFMOK9b/QuJ2eG9zwaykrQCS0o9ImFwYup/AF5lKPKxz3SbUeiR2ixj\nc5K2JXN3gU+pgBJ5zadxa5OHZe/qAQC2dhibyUlnirBvuHHXFNi4poQ1cX/Z\nYnbjwvYmrnarXmEhGTQo39ZQl7jK85RjP7r5PXW+2iW+Nz38Du7BBXvXKeQN\nOI/i\r\n=E21s\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHf/ppUcnqwUcBTWcJ3I7Cssg7lU8WJFd3+kGYPVYNbJAiEAojwVAQJjRA60T6u/8+HVmz5OfPVjKnPGwF9h5c4eJjU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.51-alpha.0-idb_1550142352383_0.7714292439901602"},"_hasShrinkwrap":false},"0.12.51-alpha.1-idb":{"name":"teambition-sdk","version":"0.12.51-alpha.1-idb","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.51-alpha.1-idb","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-Pd1DuNzevQYBGWtTe88/iStfHQXWHoMAU1uEWi8Twm34aW1vlpm6s5A/uhZB7Cl9ien8Ldb2wBjFZikhDG2gwg==","shasum":"cc6aee1cb54a39fb01d6b867bc0e09ebbe1a80d8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.51-alpha.1-idb.tgz","fileCount":428,"unpackedSize":890824,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcZVEoCRA9TVsSAnZWagAAuHcP/2UhR7upxBZv3VUetSa0\nnKsPvhPMrjOedInZIWxCQw90h+g0dfkQeG2jdDa+pO9lOpMJvqOy6wPRsApm\n0una+nHFVJhh4KEyap2E45YILHRAJI48Q3cRoP4JT4/3hTXBmId4O/0sqdko\nPes5o4e0kHPIn7wbTz+sXPLI+Nm1UXKyZcZfKF0aU+srg78dIOBQKjO9Ievu\nssr8WPyQxlEeVjnvCb1uO/U8miT7Qg9oiawMldY4/20YsSnyz6zxXqr9LBaf\nDxwaTIFnEZGK9pbMudjb78WCgPfnz46jhDuNvw2nxEw2YCzj4vwmQGF32lMn\nFs68Ay6Qkh21gsk27yEMQo/xQb6ct+KhB3C3DoOmgcSncMY8JmYiQPtov069\nMhLVWA8x4O/Dl2WvvNiYopU1/tNFDH130xa+sXVOFPamN76GL5WbDkoPjzS0\npVjpHmTPDtYJIFIuiExR4jdNnvTowrI8NqZlwCm+3LpU1Z47gVAc81kNckh8\n6XdhXjeF6aRFSqoJ2YF3SfhxarzUmsNpzVzrrmjF/CI25UqE99HSc+HyOePW\nDtIOfIVZbo9MUFU3H+z9ks1wkRlGqEXl8Dk2/RDB+Fv5ZEO+Qa+O7DagvvTQ\nqRUELS1sZ4Xki28FzaAnlR9eBxsPZQmfTJuTmFSY0VfKKpC2OMX0pDoJ2O5t\n58Xn\r\n=acDz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8TIiEM0fF5O/BErTi2NMD4hfEwc8uOgdZdyQv3KgBfQIgHZ+etweptxIw5MZdDst6JRvt7CenBhHGJoFIaQtC1mE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.51-alpha.1-idb_1550143784057_0.20114328618727662"},"_hasShrinkwrap":false},"0.12.51-alpha.2-smartgroup":{"name":"teambition-sdk","version":"0.12.51-alpha.2-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.51-alpha.2-smartgroup","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-lY8VvcQWmkmq3iCzjig04XX/2atjqjIH2Tn2OVfBZi+5K5ns5M4xgr7PZeTdAqQ+xcyBkm8+k1emwXVGyMdDuw==","shasum":"fda986c881e0afb79db141fefc1fdbb7687c5fb5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.51-alpha.2-smartgroup.tgz","fileCount":425,"unpackedSize":896930,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcaiU3CRA9TVsSAnZWagAALtYQAItb7jt8lGvCfxm43qIc\n67p1p3NqDtJW7zGyL+HZwlcvZMpDnkdcddTXMfI4KdaD24XZNqxj/FLi8L8Y\ngSuPu5zWF7C4Toosim4EJLyK3MVtOUyvvKS2H4GOts5jXA0J+ynEYjyLDrwI\n7yezZwkjfBpmB1qNKBGDbPtGy7lIB3F0X1arq52FSMRCwsnDDhoUq1OU9C5+\nKeZW27sHOB/sSLuO9NpedwNc/XMEoAz5c1tBqyOTosHKOxZGcbrjtp3JivyA\nWfvM9Ei5wsMyqcCn4uunVT9DZoDFB/n3o9IO6FcXLcEjikkUpeSreLxBQinP\nUCU9Zo3vO22LUD7j8Dv94CvXznK/f84fKWTTPYkIEAisLv4sdVofo2rbqaEM\nPs6Tb8GRxmgw3nmdk/uXldjVXXXtSysA78Qqvun7BB49d22BwWrbnOem64cn\ntQ8qzctk/fCb4gTxN6QsxgKybfLeZdQ4knbhOEWBgJHfTXzI/QK987C3OjE9\nqcg5x/aWrSS3s4jPKHwC8H7hepbku2J9PTO7lfoX1KjMRSBexhVTe+3x4fwb\nhPjPMeRcMsFVv7iqjSFaGdy2PkzYrHeAbPF82Mj6MjlAtBgrmzno4603ugQ5\nCT0oP5aV7KH4+HdtnfbL0/uL3/kgN21HimxcJG1WtGO5g2UQD7zoZglbbwnb\nXBMx\r\n=//8U\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDXu/dAxHYEiBbDw1m1DCn/MzOg+OgdSkfgv2rqCHVe4AiEAv4cwsOCUIfG9a6AqUkrZA2qRxvIbjfDFf/vTgQknYl8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.51-alpha.2-smartgroup_1550460214613_0.40892978859577545"},"_hasShrinkwrap":false},"0.12.51-alpha.3-cflock":{"name":"teambition-sdk","version":"0.12.51-alpha.3-cflock","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.51-alpha.3-cflock","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-YOpICFq3si7iSqfGFQm8XCe7RvdzNPRoNkTIMVQK970BRxQDZXoTFkBFRRDVYJubOpJyMTaPJNMwWtBHhvATiw==","shasum":"62317ab885b687bf273f4760fd486581c94b2587","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.51-alpha.3-cflock.tgz","fileCount":428,"unpackedSize":903320,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcaibICRA9TVsSAnZWagAAr68QAKFxJEck/KEaCOuEsa0B\nA0PpIOWxp8aQr0uLFpJjf66TnK6Af9DlO9rK3EokqMyxVLVk0ib7d8+ukNHM\nvO+Wa7T9fIS/CmnAXzkCcr0CfpO/UgvwrU0Srrc1BC2Qa6PNiwncxV8aul1Z\nT+TiN2lBe9iwtgmtga1tvTCj/G6RKw+0Dft0XxyQRt6ZBrRVlqHH27u7dn87\nS4rgUcIZ9vPvaPfsDDK/iUA6UP3Q8zJ4x0bDlMjeykWILD2+byp3Gkvjo6ay\nwy40/ViUez6X2unHf8V4a1kMpAaqeZzoVNA+oGUhcB3BeFr4IuoBBIv+hsKi\noiLR24542hLH18cVUXhl9xaS27rnalqAM3L43WP435UJciu+9QTBjS0FeADY\nLMdU6a7L6amlPZIy2KNRmgbJQQyY8S5r1CEhrT66JzfofADF1PFip90xUqXF\nUn57j22Z8hGTapWuFf9+uJMjZR/wtFTUmmUdnozjASmD6lKBCXGSZZhjO+/k\nHCUA3Et/UqUJQ906B/YfZNCvVn8YdDyBKh7TP6BG4Qt63NQMI+Z6B/gH0dt+\nWOy+wt06WuugiSObRUcPZKno6SlFCg2JVJRH/C1ZTax4Dz1X/XXGRV06Rv2B\nwnHIUVcGtZtELdspaAP+1KrYFTtSd+l7exr7EXBEbjt1zTCpnR8/pif+y5nn\nfIF9\r\n=+Z0z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGE2S+/L/udJW0OXBd9l82FBI752tG3U+nDdwcGNMCx+AiBtEOj6hwk9CUxGOb3QN7PrrjnDqjZckITw3+VwEifjUQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.51-alpha.3-cflock_1550460615409_0.20621668797309645"},"_hasShrinkwrap":false},"0.12.51":{"name":"teambition-sdk","version":"0.12.51","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.51","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-D7yFPrANERGWiPnQ2pQMy86Y/UOk8sZMvVEmk27RQ6kzN+t3q7ew4Iuip03EArC0agDCefXS8crgUlhq405HEQ==","shasum":"0df726ddfb1c5bd926a52e01b0e83283e42a083f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.51.tgz","fileCount":425,"unpackedSize":894283,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcaoz5CRA9TVsSAnZWagAA1DoP/AyseU91b12movlOOXXx\nTcAXhqeK8b5jJ2Kqor94/ubqAZViV2HRNwvXwSwAZt47I5gNbTamhEU/O9oF\nvbHAHG1ZLaeLBLLlSXPYEAySN65C1BDSzfiJXVv0Y0+BB3gImo5g+OtGXLun\nZP14NIgFyyiQngSYNtmCfGe4lSwePsyydxxfwycFqzy4bpqgl34Raa8ixREs\nua5c89A3QsPP2fg9N96hCPFiRao61+QnJh3X4t1GEfrL+EjCchCTdY0sCCGJ\nNiAacnsltiMffRucK7oS/oIBxO94spjE8C6UOdMZeaTQKwUtVF56YLB407fM\nIm3L9oDmGpB3PbsvJwWsFlwmXSL0sVUf6YEdnhTrvnoe/uzilookvm2nzef8\nDLFqLpYRkKi0i0XPIImKDAJD5YXQrUHK0BK03MTlZWt2X4b0UfDe8v/H+MGg\nUnejoR7JXGo/lfgt/1B4KiV0wZK17NOEbQHq664rRNNuPF2LfOPfmHM+J3SO\nIFBVZGFBt8hlDCJuB34mhnl4sXXVbHSVlwfQjIGt+7HG/+vg3pTJNpn2Hdcm\nnOL5yk5Y/pxsmunFfGNiHrF74VW7TEAdVHxz0EkbB38d7a1ibB9SjSbzxW+B\nDwbUwEffsBnEyHibwzUp4QB3tfQndPNW/IF83pKdt6KiHsx9U1ESOsUfm3GQ\n7DnY\r\n=OSIP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCM4SMxT401q9AoFyvMimvt0pYRto+6tKrarUsnC7uNngIhAOeoGPZfaXXPH2iOcAPItpa3DVHLd9w2D908J8wlwvdO"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.51_1550486777105_0.961368764720226"},"_hasShrinkwrap":false},"0.12.52-alpha.0-cgcf":{"name":"teambition-sdk","version":"0.12.52-alpha.0-cgcf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.52-alpha.0-cgcf","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-0yR/IfRWl4JdH36+32rhPeRywtt/O6efcphnEWi1pK3Rstq/xQQefRwXm5xSk4mJ9gTRBiJaKAswsDC7b18X8g==","shasum":"aca86d994124aa7cc54bce95f1ca9f7bd95d15a9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.52-alpha.0-cgcf.tgz","fileCount":425,"unpackedSize":895130,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcaphtCRA9TVsSAnZWagAAn/YQAItFblo+UmH7eGzgDrT7\nDFFSxwNS/QVhlydIbRVeX487gJT2J+rZD89q1VO8iQI7/d/lrVj7mvvw7Kv/\nIpNGy1/PRrzFfC9bUZtkUMGhU85YxhD0ojjA9RokCtMKnCG+4wgzHeMuBz8L\nmM96xPOv/3TcjKEmDkwu2E+QRLwP3DXlHoEunFV0mOgYDnUKhWpajjMRj3ph\nqTSKgNBqomt9kZSm3onfx0XZ/MpSsQYtXPSauIDuR8AIwoh1GJrfyFYNJBHP\neMcVzhsb6gKTwYO3eQUfgSUWvTqWrWqekjbYUbQVshUyG3vC5WJVwoM6SnLm\ncB+Qu/6iA5LCDFD0D8abHetwP4agrmLPrVYLqm1MrCDZB35iHggJ92ArlFRb\noi9rpk8FDAqn27ARqhhU8ZUEmyEA/SohV913hH8TeiepQp3ZLjzH2TQJaBxl\nufdAtReTEAYdh+loAZKpHuYA2biuEAAgQLHb0f1Gm/s7Xh4amB0gJZ8/1b9d\nrVztn46XJweBfoUEADASznYsTgVXgvLT4xgRKGNaw2N1/DiyPjG5lsO/q5pP\nuV/GHTasxvsJbV5Kj5TdGU0tVWjM5Dfes8NYG79FyxHBkRlLH8NIyTxRK80L\n0q18HnTEa6E1dY97bj1DEDsW5SvtvaI8gJ3nUub7K55P8jSrWnldHe2CENmR\nIB1v\r\n=aRum\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDlqH3zlvOEdUaDAyqSEFjkaNYMa9TyF0SRnn7pyh/xjwIgBUfUp6FYOsODPcdZxUthMCgE32Vsqih2KWJLF1EnNmI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.52-alpha.0-cgcf_1550489708638_0.3960942918203074"},"_hasShrinkwrap":false},"0.12.52":{"name":"teambition-sdk","version":"0.12.52","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.52","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-9VE4FHC6m6OaXR09KBLq/rJ6gVwaAjCHckjWbRNjbkMgGvo6hzTKtT6ya+XBqPLu+RQ7gS+pa8Tn6Eq/cAF4jA==","shasum":"ccf5d703dae4e8c357b2cac2cfce63d082a6cffd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.52.tgz","fileCount":428,"unpackedSize":904830,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcbRjpCRA9TVsSAnZWagAArOMP/RvKuAb9LSZlichgxbkb\n8puDEmcXJMfPkjPba6ib9jtvUuTFc8nfM8itfOna30LhwEj6R8UtLuZmZjw1\nnj4ZEr0usvLKekB/Iym+pl2f6RB8BPvPfIowcI6vNG9Nw+UD4Jt731UoomDW\nX8QLT6zbZ4pdXnRPThRfuXhMqYblae3NMPfs/kz3V4YSOOrgLdDJwd8zrRX8\nmjPwFTUs99HHqwGDGoQ4aMkQyu2rRAkMqmTI9lMjL3o+ID1slyetqndn3Y3K\nQ9LQHoQYUZDet2+p2iVS9ERxg3KQKy0MZkD8ZszsbXzVcEpVdN9PL5JrFUoW\nnT8aMxbhR3U9M7XfXm+9AXvlSdGkc4SIPtL0H/w76NZjwS3f2aqXGxgJFwz3\n9Nx4W2Z+iKyEavUljIjkfECDdUc47UKX7vba3h9w53ejJaBBD+TwLCoCXPKa\nK9sbf28xb0gyTqxnfbpzJQlCEhnf4o44jM//C1olBON2tUM7Nwn/kb5cClt9\nzefLPhpwxV2P6w0TjqjujDHe0ABd4ivEWzAQPayi+yHGjcHuofaHJExmQPRI\nPOz1ZxrTjKWBvNNaO59eyKSPnvoH0Op7IjrWmsfLz5aU4MqKqyZBAEVVbnwz\nJR6M+FzebILDCdFcB95C9vF90zdpnBLvQzDNICAVy4IBN1/e4WX/kwJyiZIY\n54Dh\r\n=L+84\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDmp9KdW3bzSDP2VmX9kSLEMLOeiGtfT3DZxlxYVvgvLAIgaIUgtluKElPCreq4u/36kOc0n7Smhl51lg8kR2bmQgQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.52_1550653672635_0.9357222011613051"},"_hasShrinkwrap":false},"0.12.53-alpha.0-idb":{"name":"teambition-sdk","version":"0.12.53-alpha.0-idb","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.53-alpha.0-idb","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-/gxZEsdUiNCEtZYNmOvPMjERCsI8pP42DPrS8uadavdzFNZ4sVWwvKaNo7/a8WH9k2Ws+uumONO2vi35RkCElg==","shasum":"b1ac1e2fe931078e85d61c1c1ff4f94713f988c5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.53-alpha.0-idb.tgz","fileCount":431,"unpackedSize":901985,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcbSCOCRA9TVsSAnZWagAAKroP/iScjAF2ddMYaCjgS81P\nl3WXxBEqsWYM2GNdh/V+0xX1UskTul6juxQ4bF4j7cH5ITWcsB2uiAAsogr3\nGDn4c0X1suiTsTEaeX2+ekbatFsfSynHO28zDQ4R/IcRQeAw0GlEZAvw9QhJ\nVakX5bQgNreebib53FltgUq52lxNvhoGxK2bTIpQy2lAGQqxN5/DaIecFwdY\nhg2zZeLZ/5u9mxZ4rgTjUYTmOsSsORz71VTLd17mKX6O3NBx2e4pLkCgZO04\n9Xf9R+DUwZvgpoxInaqlHv+uPFcPyIHs4XtWGLm29ddnIcOwoiuVD7vVHTF2\nvk6sQFCQUSHBafb2HXZQi8UdfdkMdTsmGSFrb59s5r537k6d5aZ20wucZwFb\nBA/m+XfUcuTbly2s47Bg8kYSCL4CPpQWV+fJP4v4gyyrYr9oaqtEXKS6rZTw\nJtkKpSQ/IZv+dHF1gUjgviskIBwEH8u2gTooUF9sUt0GbYv3V3dmQrsO83KH\nQfgoBkijbyyBNVVpIPUz+Q/gFkb1fedAWe9dc02meSVj+7H2DuZzSPMQv5KM\nBgHoW1sGL/sKfkY39J6K2xX9MUpdrFLukidEX7ydYr43gMGihCtMVQ+TdX32\n3wGGCFXFNomR5r+IxJiH5os/9ukEQ+UAZkPJ23+8pEqNpb2DlvSR+MpivwvK\n7KEU\r\n=6l4D\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA5BeuQ/zDvTdmEVzTsLBlv6Mxe4Ygu9j2U/DjwS/ce7AiBHNVoMvwkfYgXq7SjzQv8IhOL9y3MdnBTXUZTKHKDsdQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.53-alpha.0-idb_1550655629361_0.5880628620564685"},"_hasShrinkwrap":false},"0.12.53-alpha.1-idb":{"name":"teambition-sdk","version":"0.12.53-alpha.1-idb","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.53-alpha.1-idb","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-tzuqAAS1kNZcIyjxMM6Z+NAVERgWCSdtQ8Xu8rTM0trHswx8vFjdt88tJAFRvJHV5+E1oYmkUmxlAOBI4aZYNg==","shasum":"3d44a7561c17b1bed5e25f5395944baa1d633277","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.53-alpha.1-idb.tgz","fileCount":431,"unpackedSize":902919,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcbUfSCRA9TVsSAnZWagAAaecP+QDhHULB8J8O7m+efae/\nPN7hnLDXrUDGxS8agsOsJZtFsZF/PlK1UI3x3eMRfdjHi2xkR2zTAMhxGYIL\nL2OaiCDhhj27t7pVrBN5FxhOVtBsxbySKOy+Utl/2J9ayA7jFfCOmzD1Ll3P\nNC84XxAlnNNTveaS/jdR46hQ2cM/rKdr3zY8wR//gW75ZR14/zI+YCp+AJJl\n9fdTEalKZxs2QVx+PY2ZomIRFTPUSzVYp1G84jBUx+Z3sIjl2bnKt090ODQ8\nWW5dyGkwvbc+fLXBFSWErguBxq37RnByP4Eo82MBv49t/kAth3kLf7zkKy1W\nCvTo8Pz78WlDLIbUaBqzdxkFwMpb0wiyXBRL1pEbbmkDv5nQ4h2+Ua/jRn0r\n0p8cfuZYO3QA36wTAN8pJVLJRV+x4h2o519uLoyTemzu0xgynhAWJxgB0dbt\nOElgdnVwxAKxcZGH+0tvr8xVA8ilDd6J8TjuXsAUJKUDRoF2X+eNHqDyeoJD\n+pzS4DtSeePjm4U8N44O3jt4gfFJQeJDHEPxafCk7D2WvizHzEVv1l5dJzCf\nLx0ABd4VkF+63nRfEFQr6k/CGP0vbROS3lfTgUV7Vopq9WiBNMt8yC24eA3X\nm+nnzTBo/l146fLBpIwppNEN3Q6avAOC/MU69+aTHl2q7Ack+NyrB9CSNApr\n/ejB\r\n=zcZc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCsHz8iMUQqPlI1HlSsTX3L88QNFNa4Vcfkrm8+vXnsywIgbq4Rv6rQNPpdl+M/9S8JdDlHJJ9mSs2rN0+52o72OQo="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.53-alpha.1-idb_1550665681006_0.006773026570005669"},"_hasShrinkwrap":false},"0.12.53-alpha.2-smartgroup":{"name":"teambition-sdk","version":"0.12.53-alpha.2-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.53-alpha.2-smartgroup","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-hzg4FYz+fFBd/GgrQgqNU//1jQgrWbxCoOzZcglHDDDSnuXea03xRRJl8uIHBMwC+AhctDHwAbAkqKgDMQXgFQ==","shasum":"1b64213fdc8f61770339ab43a256498c9cc97451","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.53-alpha.2-smartgroup.tgz","fileCount":428,"unpackedSize":908168,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcbVRjCRA9TVsSAnZWagAAHSQP/3NfhsnL6IaJ4zXqGqXV\nGYh3dXTvdAgt/kaegfhqi5Sz9Tur2OmN+XNsB6tmPnSb6leBnMqU9dszvK+v\nLkVr+pip7FENL6NT58aPRtCZxPtshygW6Qs9inFPudShyz21O5ZViScui/9R\nfbwms1GC9DUPp5YwLQS6hWWk9RYUS/aRXghLnFrApmgjPmnwfl5TuyVoAalz\nMVxjHsE4i7BLpFxv2EoiMUEN0+NnhxtTLWqRAoTS/u7ZffpNDcwzBJr5UyUS\n4ppggwp4mahQw+wE7DwMNZVgBzEEMxtO1VH5b1C91yqiXCLo0QBh4cQtVX4M\nRuiObXoKImnp9HTWZlFH8kCeDk1oJc5Ho+ILEMDskKX5k3h1fc5OLizqSk/F\neaXGp7sjQBAI2+4SazzHhcyEfhjQSCzwdmaZqsgY+1OVNEQv9P5E2RGIwtVJ\neWxKXPYBwtmRETtTorviEOLNwnhtt+SPQNyTp88VvExYKKfy+sjkbJxR9lJ5\nboJsxVXr8BjY7bZSQSCXfih08BDkt2e7C98FDluhRDm24HYfEsv3ShSO10+X\ncXqAtCl+vpZ+ZvYH+HiIW2Djg5bG/OjHXWYi2gtQeCtUSC77FRBIc+Brm6di\nOTnPuT/Jd7Tw4tRkEAN7OiSA2jDP8U+LkwHFEDD88CLOoYL8vdh9aQ2jS7yx\nP09O\r\n=X3r7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDQD85+Ph2MmB/ibtizeIu4TzTDpbnf+KsczVm+uBBrQAiBqzZnIqRkmgRmOHT7TgwSz8f6VYNRGU/dJ/57RVPUBRQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.53-alpha.2-smartgroup_1550668898654_0.05862017268765474"},"_hasShrinkwrap":false},"0.12.53-alpha.3-consumerid":{"name":"teambition-sdk","version":"0.12.53-alpha.3-consumerid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.53-alpha.3-consumerid","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-ZcTzwxM6lQCVWGbG8+XhhBOFl/0tZ8tcrSQrTelSln383qdCC9wS5CoVP8x2Pk1DojNjC3KKJ+etxN0u0HLCXA==","shasum":"4b6a77859d78ce598a25c98b21183dbdaa4c24f1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.53-alpha.3-consumerid.tgz","fileCount":428,"unpackedSize":905101,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcbsRPCRA9TVsSAnZWagAAVwoP/ReWeOGns/nHlG+GNWfY\nNV1V01eOxc9RnKb0xWPDeZYenVnpyFL5WtT48JeCkJWeH6MZKQ/Ud+Qsr2rr\nYjnkz8lxVxJhsq2nrs9AkOhdeCoUUbh+zkdUV4qg4YwIGA8MQdsNSwhKoNrt\nujfoWA70qc7jcvGRVXeRgit09Fx9o6mbvLVbut66c86v+8DUTk/dJpdxm+Nb\n5akm0FzKc68HOIWbv5t7rnmFm+/UMLT1WgHSFIK8WCv+HE0x7dnA17cdUy+6\n/gCc9QC5Es83t9XM1vkqs53yAwywWl28ZaHtHbDiMSQ1gC0Sl9oQJKs28N4c\nMNr4P5f+BLYH1A8DeeAaAcveLVLYxcdLIcxFZT1a8XcGxm4iKv22ipxUSz85\nTgPiUmMkusLQr6kYGqD70nJgvC09iDwLV48lzcWCvxDOcxcPaanecbhoKest\nEvPKo1ME0Fm2Fa1Kj0RuFhdQM+xxJBgmGpAsokQdnIQEb18MkaLndlGiJHM/\nd3JoOSCyK36ycX5dx5sM/VBLDLr9HGtC5fpIAQexFiKHA4EllnAk37rw6WTU\nTcVLFraDH08gONVIknq/zKV5/JRm8zhJulaAxcN97+f4EFNBllDr6JBgDbcF\nyxw39GLfx/OfkfBUJpUFwRnpLYE1dpCb5ItLbU78/xFvKwhHwHjJuE4HqZxE\nG05f\r\n=1/cy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDkSZkehGGhLeTmSxkxhoF82UYqQbGXfZPpXUAIUi1kFgIgcZogLWj+QHlYJ8XXRJIYfj9sMmKS/PDVCAfxEiMen6M="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.53-alpha.3-consumerid_1550763087187_0.23629584759832944"},"_hasShrinkwrap":false},"0.12.53-alpha.4-consumerid":{"name":"teambition-sdk","version":"0.12.53-alpha.4-consumerid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.53-alpha.4-consumerid","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-/SSwzWFLlFnwhF21Y1WsHWXQOOwjgSdQAII13bALESVEd8bkhICODYwKoT04cvpK6MRYUIHOS9ApD1JMLbz8aQ==","shasum":"8fe98b939c4c04228f74ea6e7ae9761e9791e829","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.53-alpha.4-consumerid.tgz","fileCount":428,"unpackedSize":905347,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcbseoCRA9TVsSAnZWagAAXWcQAJuSZ1NLCLS+0Dy3wUOU\nVv0f5TYnFcufo3TnPHrLPZEcOBMnP/uLtP5WfG6TZKUD6VPxNt1VsJGuehgG\n+c8D09ufb5H9US5mel+cgTPz1wXvBBQ7CatOQor5HYSSB9PBygun0hoYVaUn\nQzqdpJJ0vzygdAcwYVDqGx+YQVHlsLp5d1Mo2dflgGNXSydMf6L4QOvzlFK9\nKcFP6ruKa8oUtImumgLvnHbPHRoKqUgKd9rnAgR5HXPSnR/OusIKmRp22hvo\nsqqtAfmoY+bmniPUps9UkeIASTJvbc/igQrRgTuhI/pBAFKofyZkX6A+MupJ\nIVBhij+2fZHEWRAwXMSTy+ww5BLBCX6cWOBb/mXpS8SuLXPyU9yxZrvp03Nq\n4hIBKX/0Ftfzedu/55fXh1J5vfJBvRR9+lgltBxEAEhkJupGH2jmvF4u3F73\n46mpwloCGEFI4xOtaoJUywGJ4iIo0jRn5vFC5zKDOMVpidOqyrXys+wFsMHV\nosiaYeuPkzUpRq6eRHVq+oUlB3OpGl2nosMRtW2kPng8A3CYX8wMgK8UmFfp\nnaCz3g9RvVPX/hlo4GJ3JD1lL7HEuzzmvTHyU7EzaqQvrBrouKfpk6KUCfmI\nzx/6ggrEsW725sKTS5nZDbah+MNzG8gReAF36+hb1zCkUn2mox5Gddqv6wKC\nSnPH\r\n=mK8V\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCsviwUJ3uwo+RYIw9Ia5KOR8MbeUj+sxdyYVqMucbxiwIhAIRAWTldfGmgHiQowmTJIFoIEls5z3T6k3zhJAsltf2t"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.53-alpha.4-consumerid_1550763943342_0.8264902359532045"},"_hasShrinkwrap":false},"0.12.53-alpha.5-graphql":{"name":"teambition-sdk","version":"0.12.53-alpha.5-graphql","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.53-alpha.5-graphql","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-S6ajw67+vn4EhfTnkwGVZpGImDXvWF/xZf9pTRRewuw25qkWFR8Zg9FoWRbJO5y0sPq0Vsg1mBgZaqsGRsMAFg==","shasum":"46b5276edb99eaec2f07f801bf9439177d92dd09","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.53-alpha.5-graphql.tgz","fileCount":428,"unpackedSize":906507,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcb41MCRA9TVsSAnZWagAAMNwP/0bzTYHzEPiqlld2lvj7\n+YU3RYph997naucxhsCt+oXr5Z0rNY3U5Vua/XVrsMKH10auE6+JfWmnhJRw\nwFZP4mdr3osAXqVfm6Q5rVpzU2h8bDyiU18NxYZKJkt7tKX0sTh4Smu3cf1g\ncpgajRJXSdWStNsc0FIIceh50M5BFV9koJ8LlwoN+IhJnOe6rV/O3L8PyC14\nkLIg5j2D83csq65cXQ0aqY/KJQ9elpmP+soAqQgOiSebt1f4XyJpIApd2eCu\n/YIBzs9n280qq9UiJi/kXdGan6NWHUd/JjEOlIVjFDgupnL8i1xtREK1Zv0F\nyO7eiwhRkHK4xtOeIRQImfHfmKhcG1zEnfLhaHzD88HGxbpGwMR+Mz9ADwGV\nxE2mSKKdyu/mC3D5aHAdI3MLzykvrxtVrqRwvKXabxQ1mJ4eub8By7HeUXVb\nUURWQ6ub6zivLCHMlR+Nc/jELiAfQfJMyEXVhk4FeNbI4ofv5E0WUmKSY8wU\n6+L/5P3Y4Qt6nxJFdM8Qn+zQofGHFGHBY5XzOXgiM8qzPmttEyeC9MpHs1/A\nCzxQUEPxt1BDpJsNDnV8Td2zHEygPZhOB2JEKVCmR7Ji7LgAlVZGwYp12frk\nq8Uh258FeVrs4sF1F+TohdjEx+1tJIs6sA2+XSdqD7EJb+61qhtVQIZLgOg+\nMmpr\r\n=AXU2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEVevrRjI2vKZoiY1n/Lwy1HB3j1KJ3ewo6EMXhx0bAJAiAQgq+bpbG9lFj1qk6hCkksxAfDvUrQAf3Oqy8JWBKBWg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.53-alpha.5-graphql_1550814539749_0.2913768590952688"},"_hasShrinkwrap":false},"0.12.53-alpha.6-tapestry":{"name":"teambition-sdk","version":"0.12.53-alpha.6-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.53-alpha.6-tapestry","_nodeVersion":"8.11.4","_npmVersion":"6.7.0","dist":{"integrity":"sha512-2ozO7JxS3al1rc+wKgYJLQMs+erLGrtZfOJC3FtPPPuG1FnOTboQetr3rmdv1pz4/aQacNecVb/Xvuw08YH3pA==","shasum":"c06fb8660673267f569fee1db710c05bb1be08a7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.53-alpha.6-tapestry.tgz","fileCount":428,"unpackedSize":905136,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcd3d4CRA9TVsSAnZWagAAwaoP/i93NK+XTDsLEDWYYmtp\nfNEWnn1t8vZzVpLxQ5Y6FLAtMPEKvt1dD8EaRJfiCAOCKszS2eYUYn72EwAa\nN/gbsuKYA1S1fDnNOCHcOZXhC+LzYUXldci/yjJTHa5M3WFA9z78TPLJ231z\n44w55eaMMF2glqpH83MiebZCb2Y/O9z/7qAEpLUeZqmF0o9xoRulK0t7DSkp\nD8aF8loHrrfp0S4yd/7nDdkfmSqMnY8ix+KT02Y8D7+/zrn22yVbbjpiKRU1\n+H8krHkCHPgvSGPTl2xqsdwTI94hxcICGlldHLnY6pseVvDLWcK1rfNyOQib\nUx0P1axTnwVdq7wJglsVLJoPX9lRXlr0r75e/uzi3y8OIVZ8DB2qsOIHgZRG\nddfVyu0GPARzfFVAh7moe5UEa7+zK9IBfHBEDB+3jFLg/UJcbE7TBigOTC0M\nmavP7YThYwE+8DRyQjzHFeEQQKrC3YCndykPsnWAdk4JyLx8qi5F3H9luBSE\nE9BztgdmSgFN1GqjgTyMzoBmJw68FG8LGn9N34Exibazt98ODuyGJUjOJZi+\nZ/ay41yFS7HpabTF0Chb1clhwCrh9foIavmvVP+GuZpDPeL5SzB06Ee5i+BR\ntJwOtaItSyDn/lINIM5heQQr3k2+z/VQHYOlmD7o9bhsX/8COw8szmUEB2qT\nTHjG\r\n=A24x\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBkmLt6EW5g26JZz29+30FH0JzVs0j55AsIJ97C5WJSfAiB7EIxO6JuDiMtsRR6fhIHStH0qdDwah6+vHc/DfIXXsQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.53-alpha.6-tapestry_1551333239985_0.9492037638297368"},"_hasShrinkwrap":false},"0.12.53":{"name":"teambition-sdk","version":"0.12.53","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.53","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-Z+1jqIk7KsJPrWqQHgliF4xf3w9dWB/nA9TSt3NLPXQ4530Qg7n6bfYKELXc0d2qk9RoopP4J2oFTn3XOipoSA==","shasum":"a5bb122fff36ccc3fada2d10d35e5ae57c5ffcf9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.53.tgz","fileCount":428,"unpackedSize":904136,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcePzOCRA9TVsSAnZWagAAW9gP/jlsL02F4hJWEiQ78gSR\nTm7C1cUaoYY+2/Q1v8Mz4IMg8qofdN7qPNScoDkF4m2xgBX16oMxiysf2uDJ\nXdKcsW0Ot4DVrGofD5aFBLDjrNkO/qV1nyP3uxrEszQVbUkAz/lqFYcLliZq\nSG458QTrLFgqJR4e8tIE21CV7RWxCyNTa455HzvVjzt0AWDJY1/10Etjgiuc\nMzeqWpTcwM7U2a6PKdIa2Nto/UHEz7gggsGyl7gBrHKa0tcCwGkCGdOvVHaQ\nfC1NJUuOGlEAkXtugjHaaim6Sbd4sc6YZK0JjtKxoUpglMRa3LyK39MmqJMY\nIB7AlVtOklcEMCZWs14TINE1hMiefL+xKVy0CHMIMQuMvOic6HlBc9udvSOY\nnEdrkj0yCpfsonbTj7YDDPxgsFWZaBcR55KxrjJOSJRRskJCBW9E0TIk8/xG\n7MU8sSgdOC5U+7VUN66imlIpPifgdvNlsVEWj5/W7u1lBOsCGJn9Rjqg4LCc\nJ/NEdrSHegNWW2p+CVH3AkzfecyB+FtTC68pciea1VDGaH8tLVtJ30ebAZTN\nHSeU4oLG8wW5j6hKt1L9dybo8hyD5p/qr/Euy20tgfdmZo4ML1LubzqvAB0S\nsBRKWBI6j9NENDaHe/blvbXDPDdgSG2dWVRZ68f0CU1FW5OFf1oKPVjeT4Hu\nAuy+\r\n=bAPg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHp/mHfDO6m7Ubyc4xdCxhGzHTD9TVe3oWbU1HFSHg3oAiA/HKUCxqxpOsEaHO/n3V7KAe2rYAdRQK7IxOphjuUwWg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.53_1551432909640_0.4498547482720492"},"_hasShrinkwrap":false},"0.12.54-alpha.0-tapestry":{"name":"teambition-sdk","version":"0.12.54-alpha.0-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.54-alpha.0-tapestry","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-03kuCU5YIbSh59GJxPe8p9Zz3c/ck+iutUaX3aE/n0JZDjuxpq7yPSt3WE2MxofFEhrYJM7CAO/eq+rgX8vLyg==","shasum":"0469e2015987038f393098f489a0bfc661335972","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.54-alpha.0-tapestry.tgz","fileCount":428,"unpackedSize":904442,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcf2s3CRA9TVsSAnZWagAArygQAI4XV8aVvTiKrW1Ell1W\nt2hzsmULYKiWo4cGu/G6tElpYsoqWGRFdlib1pkErzY5k6PQBKeKsT7gIl6l\nipUP+Dm6sb/PybS0NMgL97dtIfzcQ20bGf6cZhETfcR65a/gZ6DpoKM0BQ1B\nSn0bpUhctoPDs2GVUdnu6KZdzLAufJHblKJqZFGcTlSgvOcMFxY39dZIVbhh\nHgjxwi7WrOuwZJH4WR8iUjYHg8zZ9+TWUGB0M3NA2WQcHyRGQaxeT+DHcEvs\neeBLqsJtZuC8yKqE8C3F6lbpxKVUgHkHxA6ncPUmJ1PRwjkTrrH45l/se+LV\nh/6nqXcMuB/1fgNhX6D0mdi9zGTVjRPnGDVsNViMwl/zNQNJNdVGI06zbuPm\nnVcMZP0TaXDXMAFLiRYThCDt33gNE0W3qpNZuBLn0i1Hzypb0aP6jRRTwtKe\nd1goAaTmEyaRINaSniFovGORJx+uhT5Z4R8hCI4gGfM+KUXHzQwT6Fmqa6g2\nY653ckT07uKRTQv4f8gjFlfRiv6yM9VN45ivvtW+OF3dUJn8BF3HJ2+8QV1X\nQK+9Z1BBGc7a1cmaV9yYBk6O34bserID384g2kopR99Y7b1igWqDbTxuxccO\n8j3xbFxNEVY7VRfHf3sVOUY9KcuLgvYIFvc80jVxr4ujafjMiEsReQHH5ar2\nkAA5\r\n=lLFy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDazcmgUfuPKGiyjZ8ThlGX+WFx9cBqTeYIrrU/cCYl+gIgBglPCNL+H5pvB8MahE4emjI8TArkZwSPN+Aeog/DttI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.54-alpha.0-tapestry_1551854391132_0.19890310932071897"},"_hasShrinkwrap":false},"0.12.54-alpha.1-project":{"name":"teambition-sdk","version":"0.12.54-alpha.1-project","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.54-alpha.1-project","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-aZmw5vBEMeZFp5S0WFjmTM0FnCdcXgAv6Ib1N+3ulrYnmG6iroCtwqHoPKzA1yACSqnPEnEbCnAZf2Hno0WvOA==","shasum":"f812274fc6bb90ab81d257e4542de4455861a336","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.54-alpha.1-project.tgz","fileCount":428,"unpackedSize":904614,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcf57ECRA9TVsSAnZWagAA5BsP/RBEpxd2OK4SLaW8Ki+D\ngoUTnEYbcH8LO6347QzUgNhVIS05bdoLqgHCFCEcvz8KD9ooTnheXucpNU3q\nSWHmaxDbGwzoYJFRNPKliTiaFf5q3psN0HkBkpn7WBz8huPztAJmw+lfXlvO\nNRerbP1NFS5UgDQLglat6k4K8D937L/0pY+3htNWuJfTfFz7hxUtlwifMjC5\nCYWRFkCl/xnG8MT3i/WlQsQ8Eqc1JcqvSkDsteNrjyb+9bqf5CpF4Q/wAFLp\nAmW6mCDSBq8xqZZuAs7Ef3Eeu14anoe3izjWo/NvY3pY7pdDIWjVmQIyUil+\nA2quzEZYIWTyWlGNxX0ZA+n3WH2KCGM8wT357EJRReqci6g7XNyhafWS3k96\nq+ewf/A4q/eEfx7rPpROzYdyiBHO6m6zx90mzRWbXJRvQmDpA97dUK1FlPuq\nGrtvM1Szn8m4d1a05nPG5Hf4ijfix3AGkA917Nht6XlnA4oNkq+VJ3dDb2RE\nPJQbII5vBo7fbql7pwSKWr/ykK94hsMLFZMSTqkLrR4zdhurbNIKmf1iFCmI\n0CRyuP7/6esQ5wrdAWX26V4QCy4A4nknEuFAfz0igCqqPavEYbDRrintGxln\n/cABkYoLkZ7pM9dCn57edMIpQOnPRBjrKNqI2rjLSy6XJAKnh3/h44kTZCWG\nqIoI\r\n=ppkL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCafpmPTv69SM2WqKA7oRvAmnWDPgfV79rEIgs3M+zmuQIhAItQpzGNe7O0th0NvP2Ev06t4YCRvlQPQXM1tVysu+A/"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.54-alpha.1-project_1551867587509_0.45848827481278165"},"_hasShrinkwrap":false},"0.12.54-alpha.2-idb":{"name":"teambition-sdk","version":"0.12.54-alpha.2-idb","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.54-alpha.2-idb","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-yyu9QVoWgPrVue1zMEua7bDxCyHVV9BVN6fD7J4giH69hhUGrusXSSfBwN19ACLKe560SX99PZby9zgUz6kgvA==","shasum":"80041a9909ecf79cff9e06a963f0384f2ce0b996","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.54-alpha.2-idb.tgz","fileCount":431,"unpackedSize":902225,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcf7GmCRA9TVsSAnZWagAA1mEP+wVWlF5rLwvR+cipSWsg\n8dZgJmoMyaRa5JqiRpAeYE0pJEs2ioh50kcgUMbI8T0qsNHyBfF/eVLeDpVS\nCjuzyZZ3TmXJFHm9K+Jd/qBI7KKEyl15g/Silbg7+ORQ+J5+udkG4a9h5Ccn\nfLVkeCJexOBS8y0iwyBgCZLNE7BP1xfZ6p8ebduKy3VTz7LPWjCP0Nly+3hJ\nUHL0zg/1sof/XPDslox0+r8PQ2cve3r7iVkJ9Hwn3fVkrtDgSjVPBXfGCsTD\namUTCqVFSwJFZZ53D/oC5c8G72T0svuVyUaFuL6oowDpNod4+vWtdNBxHfjI\nEFYM3qn+GS3aEQ3l3KsWfTbs6IVbTqKU35VLImG16trNxcxsKsjtmypakGTH\nfsvzdforVV3Vbm6sN2hNcqHF6IyFQzgER9qAMZbW0BaT+OF0+DFiZsCW2mGc\nsaFp2Rbgu0avc4SFU64y0Gkx9vSxPcJayvqMjvfbsupW4iJ5jjsVGyAiy6WT\nlhQOhusmhlAW7PUxLX9Qsvo9BSIQpUIJxcBHnqOOWcRmkslcXsyN4TVXckJI\nteMAXBxXxNXEpQSNep4y77whmCPP+D1EijetLHe/krrOcDDhqkE/fa1m9Sw8\n1oqgsQHjQWIMiVvql3xXwiBkYpFxlKH6+NF1PP5+lW5sjkYQF5hk5JMyeUPs\nXktH\r\n=idPY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDg/U9xJ94sB9IerttuJAKPr5npv7fMLzEq5/oHhj6kDwIgEN0qYW3u3qbL/9EVaONuLVzlGfl8QzAD9Jich3JdIuM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.54-alpha.2-idb_1551872421561_0.14480264569091972"},"_hasShrinkwrap":false},"0.12.54-alpha.3-smartgroup":{"name":"teambition-sdk","version":"0.12.54-alpha.3-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.54-alpha.3-smartgroup","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-3azANewskQw3bYEOloHwW4pTyFmOK2xqh8t7mlSXPuS3PU49J4UUf5LBd41amYvNAOLiVGGOdKtE2g/HNQ9nRg==","shasum":"bef88420f6e6ebddf719eb4ce54bcf4d9bb87090","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.54-alpha.3-smartgroup.tgz","fileCount":428,"unpackedSize":907474,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcgLjvCRA9TVsSAnZWagAA1u0P/0ZcqoHUREbk00nyhZ44\nJwGeiavUrNSHfo5Md1iP30NR0D7vUkvj8rHMdjLmu75R3DR1C7cu3MlIlBiA\nRmP/DQroDrP+ibWAFB+3xvc7kjZau3UlFn2SkDjnjs5EmKojmY7p4jbTgyHa\nMGDT7Tnp/Ct8uEzaaBZ7PDCPY30eu6CMyTctyJyFMuqUN4xgGTWFEOvsOU+J\ncmTly1SqJRQpsRY75gc0dzoo25+/RFQrj+UnOT1k0gPOPPcB5nUuB3P5mgh4\nJxH+YehQBztroTMuNeuyngX2KOmP+uSBpiEhnhlrhH/2nFkB73EtyOjDShak\nNrHUQEKYsX+FqddYXXiKTJaKwlTR7u6FJ5EHhTgoQwxct7s/BSC6KG0+SgIS\nNL9xbnE2I8tyBJKFbfm9LJWAL8LH1QgXNj5Lp+ui7oscsw7Bi9m5+TRaOSI3\n2ASyhaHUB4FNSNNV9c+yt78zOCkxOWSXLwsCK3y5VOyQXkgp175tBUWNEKVl\nQ/569/6rY8tZhMwZ30Sw6c8C0ariNieRlMuGGmXBrK2IA4BwBwYk1i7Mgho8\nfHhBV9sTy7MTSxvCl1x6vqF0qGyYbdigj6bjXFwklHjOiZERSQHvfCTalUy1\nll86PseT5b9BepPIAqeeayHXvP0ljRvQvxtsgga8v+62XJKJJyOz2AsOGzFj\n9PEC\r\n=tvJz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAGlQdHUUZXV/5/HYjjM5xaUFACQ2sCia2VkB2QYTGQwAiBdgsavhvpYAXvPCQL7/9f5v/LuWSfzuQEDgL75uDezXA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.54-alpha.3-smartgroup_1551939823201_0.3193021974409571"},"_hasShrinkwrap":false},"0.12.54-alpha.4-smartgroup":{"name":"teambition-sdk","version":"0.12.54-alpha.4-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.54-alpha.4-smartgroup","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-N3oxzKTPWU9+wyNZiL7vC1pyudOgYm1FVEL7a+S6pAToqGgCBOmA7vY6grmydyT4JfP6SclSLR8UYcKqtTWjJw==","shasum":"2aa0b4328b498937534a85d4cea40dd27928fa2c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.54-alpha.4-smartgroup.tgz","fileCount":428,"unpackedSize":907763,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcgMCYCRA9TVsSAnZWagAA7PgP/2Vl/ImxQraFIMN2GTrX\nDfHl56VGmNDDRD/wcYtznMRg4P/vUzWqmUO6ziRCCCkmrDgxQ5gUEvQAJJvz\nKARU29C2XtUCmbicx8/4dEqPFMoRIhr2SNFboSlBuQ+RZARRFYl9KX85L+8R\nUENXESX472Q0kbSdCUenJeIEuP/MZGDtNLQuiHPT2TzTnZopQjTRS8ArzT4q\n3sfw0h386sFaOKMWibVcZVYCLhuhvWix4Pduq7JOaazrBIpA5qGMP+3dIDRL\n3EjI+bess2tpRs1qKzyuhyfT9JghgPXYxNi+8IATh7ASGKUULFoB4Vw+nTdo\nD3YzAXVJ6etM2LVzKEERyjLIwfJFgDLMOTO/uBKwYjRE4qwJzlhaKnVgfGrt\nmSRkwSbFFvvLv+Ai7lCcX8ksOkO0qabH0l41jFLBMbtKwhkD1obSFm4NpD3V\nBuZkv9Al4J1WpfhSo/5F3FvTjOEw2HYLkTxum1yGlhrwyY/bSxOA8DoJ1bUa\nbiErruVRwEAhEmdz2lkFL2VPvydz1l8pjCwuGHZydwShey88CibwAo2VfXWB\niA8u0GscF5sV9KKUSgO6CEvmNH8n4mh/q90s9z3X1Mpql/xSPvvwf4zRsbOB\nqg2xPuas+oRCp3zbi38Ocg12afKICieyyhvtygTxbtDui8QSGTiUGy/t7Oeh\nFUTE\r\n=WLFe\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD4N0EF1ev7U33lGNMOFHoxfJwMSWYA/dKWf4eOT0AxswIgaIVGjWjK7qs1+dkjEYgjdMke1YWPQWb/7XWKCqGX/o4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.54-alpha.4-smartgroup_1551941783873_0.2468198467285263"},"_hasShrinkwrap":false},"0.12.54-alpha.5-padding":{"name":"teambition-sdk","version":"0.12.54-alpha.5-padding","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.54-alpha.5-padding","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-3qUfZq/PhCa2UHBDXXb3ez3zL/lonoOO5xB6F6OWiCkhBGnczlMItDADfTN4xnygLQqumvVP7Nc22PY0AA3AsA==","shasum":"182a95a8db492a59ab5f6ed0cbfecd1fcebb60e8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.54-alpha.5-padding.tgz","fileCount":428,"unpackedSize":904848,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcggrmCRA9TVsSAnZWagAAQOMP/A7szOS0iQr1Kn5AT8go\n8lP993xnO5WXECgUtuGq7ToKJErrPL4paYlN53+WMhIfA4kvkIoEpYGnVa92\nUO2Ne+iypsCE3Jn+bzx06euWgODSyT38dPTlsmDlA2WjAonv53KSvLjka8d0\nevDXOVuatPUbG05uhcZ76Q0vRdMv05u2q6AmDN47VNV4hAO78tBT0GdPxr6m\nug6aGkTtneMkWxWjIT1pacHOAiESt5LK43ekYoGVFIRP9lMkzUZ2tpvDcWkZ\nFaOwWvBKgyhRPBB2jvRjDsfpbfTmJoWlGx7k/SomhDC+HWu19HdZHFtKUTUx\nlTWRaZCCrlvBvbhMSOB4GU6Er+8zp5ljGrdBRksK8nz2df+TGq3U3GUEdFIE\nn0YEVH7gwWuWgwQSwXgYnP1cc6cIGk1fTH7VG2a0FJzGr3MpDGsi2SeFrio/\nDsLDnhlMxBTZyGKi2BkrJ6eZeMKhkAD9327y906oVD2MiUmaW4R7URwOMvnW\nljR/IZTXlzu2NB0iHFYR2FLlNdY9X2VTT4hVnscFhFIeOYapx2M54oD6urKS\nw/qEK50PEalZTmo4Xt0haYyBHBT1xOVlguHWv7RHuwZQP2T+YFmEjjzvvaMt\nw0BeDKp1BD4dwxxAR1KTBo6bbSCPbp6jh/B6StGjzyLap8Er0XJ4YqorlBm8\nOMSO\r\n=dbgv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCJhtq0tLcHCIxAipxeXRGQAKiVYpWLdKg0Ou6ai1z0vgIgYZMFbfrMhsDWz6X8Jr9iPP1sEOXFg5AVT9M1bvHOdfY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.54-alpha.5-padding_1552026341582_0.8940976269927596"},"_hasShrinkwrap":false},"0.12.54-alpha.6-smartgroup":{"name":"teambition-sdk","version":"0.12.54-alpha.6-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.54-alpha.6-smartgroup","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-yUGb+tC88dSVBSUedLs8ev3zIzX5Adpr2lm0iZTvXw/4riwt3oPszboxQmgXfQjXvCAcQ7wt4iunZkw7qz+rKA==","shasum":"3930a3e89e03d362ffd3e9ff79d3844f9415e0d7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.54-alpha.6-smartgroup.tgz","fileCount":428,"unpackedSize":905784,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJch1kkCRA9TVsSAnZWagAAO04P+QBxGoptcfo5c+2iEMeN\ncnTzMRz46d62wzjJK3uNQXbs898luizx1ZfaRdm3qAzO83F/b2xdW4UnYNfX\nhzUUjwJV9bFqPiL1VjI6azu4pBwZV1v+nRj+Wi7c8Bsut1/IahFaMAeEjVqL\nWP6ZF62bJdPc5CJeRDjQLgYE3PwBdsVUM8Z7KqFTq7IuHP319+emBVSEwKqj\nPDQYlnugLFG7YunHjfSmS9h08XUMdcpavZx8lpnlZTlO0CtOhjkOTNEXo0Gr\n1voKpipQlN2iEz5RwspKzZmjTA9cDVPlryo4Bpc+D+p0KHhMuJ3aYf6CRmEy\noQV0ojIQHG09sLI4fmzrjTyNsWsWGrUA4u9oXXVNvf2+AAnHBZ5lCx2zSPQW\nvSOVU6sadaWpUheSgEWs/1z6GzBA3GfAxyabANULhns9cVkJjFb3tL2RM60v\njD/j0arTOwm9zU52NIojeQivnT0GD/B5F6W02RdSCvJl4SUsQyjjspwY2sTp\n2m8Aapohphiw6829wPAD08H2/i2JLtbtEFb9SJy98+dZTW/7fEbaLbJhyE7y\niS8fxSaapf+cIj7RK7iEPoCphm/PXlsVDdkAHMzKqjJP2x9+UHBfunpyC33S\nicIkN3X66ADbthLRLr7JjMnDxMRsZfqrttoo8AAozABCAAD3ltKzJmyVzG0Z\nsDwN\r\n=L2FO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGpdFVzv42epw8jjWkVCDKtbPr7VWKgUKuddIrGX4kbNAiB1oixKjzG0rNwKa+mXLbrT7GF/472BYW0DVsnVhkHxKA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.54-alpha.6-smartgroup_1552374051717_0.5719223039381629"},"_hasShrinkwrap":false},"0.12.54-alpha.7-projtag":{"name":"teambition-sdk","version":"0.12.54-alpha.7-projtag","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.54-alpha.7-projtag","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-CmjWd4OFnuX2yhjeQ7FLnL1MQaxC3Eaafgq4p8d2ZDbG71eWs7Z5zDxO0GT1FbqvceKKUgNbghNsrGxHps9PJw==","shasum":"3a99c98a932b0c04e14b0e0e2ae9a58e242c470c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.54-alpha.7-projtag.tgz","fileCount":428,"unpackedSize":904624,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJch3HBCRA9TVsSAnZWagAAE/YP+wWJC4c+9ta6keTN4qce\nv2Q5quH7HUKcQpV7EEWKBvxVdF6TjW186hf0HE/CzzsU22UtUHUy6MZwBDrh\ntpWbwq9YAH+uqE655GObvIMHR27kYr8agj7CwMpP3DSngxo0m/5I0/Mj/u8z\nb1u7OZLpx7JfApx/O9UG1F3pdSbq390szWTpqtxFpOpDpFhRx7Erqjw11WAB\njOuxnsRHwVX90Yil/+AmnfkkWoNZgmcqlzXs6Os5qGODpM7xGJtGSSI53awB\nDAcnno7OA8xeMfMAAQEsZLk0vD3ueDdhzT1rfYaC5vfiNoYSAqZ8NB9DYAQW\nZhzNbKnA3g4OmuGC6eabk67HrPNLnWbrenEfIuvG1OTNfwMgVSuR33ZTkgC4\nNTR3yGURd4jVc79ZPyBknW95G4gC+2NfRDhA6DbNmEFnKwBvdhuep/1EntWm\nknqvu5UvE42QORPeasdxyZcgcojGOzdRRsddrDGEAR0HeXf3TIQf3YtwLRZ0\n3bcQ/xpqwoU5tuQ8BiQqeo+lyzrVhZiDRvIJM59BnY1ZLq5nYz7ItrOwYZcR\nYQKUyC76QsbxOvPrZu77WFjJW+FMDXhQmuxqVOSFyCjuiRaFcnCwAGyHLwAN\nSfQb7ZWfJ5tSlwg/GJr1qUOzSNkcAVEY622G0IDwsITSRWAZ3qisAwQWvXbT\nbBMr\r\n=falN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLk6ydfGT8vd0zK9FEQ3M8TPUXod+p8tNRxHSjhji0RQIgQP68nW8m62aDGufvt/ZNcShpTyCcLOIEuZSfLLeC+r8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.54-alpha.7-projtag_1552380352511_0.501774351349219"},"_hasShrinkwrap":false},"0.12.54":{"name":"teambition-sdk","version":"0.12.54","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.54","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-vWqvS3snJQK0aXaQ6p0uZ017cK93JwAzoXCh+ZYuevPDCQG8qGMfroVH7Rz0cIupce1NuXQvOQnD6JN2mh9G6g==","shasum":"ed89c41a976dc33816fa2711a3e0620b32c635d7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.54.tgz","fileCount":428,"unpackedSize":904427,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJch3NpCRA9TVsSAnZWagAAujAP/2SA+/OpjUe+v9uYJzsV\nozq2FvKjM5ARceA7ZcTu6XA+SmZTEmDJx7BorIRF40kDYtNVBOYFEUwGp4ul\n3dspTFZqT43PUC24xXG7F8DifjSzla3HFQ9cQW/T5N4F/iH+4Uy+nhpbR1Dw\noQT1/Zcq/eVuFhZz2MQxay0SH1NzUHi14PhynHtlewhF7pyqYHjuR5Hyqe04\nP0LKrW+yIf8QoAmtMRLF+kAT1E1DuBVQy3oeghmvVwgO8tG78x5XtYO9jD7X\nieLN38RrBpBIbIwYwrQznzmBaRjghmrKHlKuREVvRU1stb1dyRXhEfbMSy7d\nFYeWoyG4Zx3jUiOCzsUTyokedDbI5TKAJM9I93ZJUaMd6iYfDF8KI7zPd+Ao\nCQd/p00n1gYVfhMpCcUgc4FSljcOGkVm/twkCJTdWw3BFlWFYjhnho48RZHE\nKnHeGnEr/jHk2dSqM7cO6JRaq1PLCzfE6S5iHiBKr+U177FhUZnOmXWmIF5/\nKpm3Q331i/asUAeIrIxij2xOK1J57FzV++61Yqqm7vDM5m9KdlJ+aUXkZvMJ\n0+s9tF+jrUvm0B8SddsmrBygAb6dDc3VltWf8Hh8rt0494as1szsOBwIPkwu\nCaBlU3VZspVlf9wJzQA9Lu/OqgktG6A7MF7H1Pkba0zSOqv4UfxXpkD0TBo9\nz/ZQ\r\n=AI/g\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICEVrUWEbixNsicw7pmkWaSydmfvq+bPqtG/QDpbleEkAiASALmSSLgbfS/GabYBLtQ0Tk0JgbZvb5bH48NQu7SdDw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.54_1552380776276_0.8833055665820355"},"_hasShrinkwrap":false},"0.12.55-alpha.0-useropenid":{"name":"teambition-sdk","version":"0.12.55-alpha.0-useropenid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.0-useropenid","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-7+jwHbCs3D1YhVIaYk7I+FJbKvgN6Q7ruHzvZZFYsR/eChS39GI3B3Y9vm1zPK5jGDgNb6kF5JQ5VC6HY0KKkQ==","shasum":"0fc569b2a3dd9632caa05fe12eedc1faf264703a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.0-useropenid.tgz","fileCount":428,"unpackedSize":904656,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJciM92CRA9TVsSAnZWagAAnwkP/iZy24oyEiAZdIuPbNhO\n1V+60KifmNYIi2i7/lRz7BHhUDzBORvAldZx7jeaV2XKQ2E+ENEmZGvjCN2R\nH0nepJJLcsDXSs/V38vlLq28JGYDW+TiMLjONCpu7d9I98vitkRd1j4TAG2i\n0AL2hJLrOKhPIUEylLdLNW0Roxhsb4tRQ5X1y+pQyNSW3ZQodRChyRzs1QFJ\nU29kxgQkUA4EWsBfPViwVBu7k9TsVTDt5z0HxBe1JTf+W3oLNhGDaQS+S3Z+\nxW43OrnfXielmD9GxjL6prVn1VE18lNWsDBhrmGHlwdPEfZekVZtHuiTbnyX\nEZDLylaPjUtfvIf55R38FSjzrkm5scwGVuyg7v2hCtOtVCdXTb1eBZJEaFDF\nw4QwXQ3VHTL19EmFCXdKN+8RtbA8+1qEJVYePmxEAJMMBfbV1V34/mT3VvEZ\nwsfXJRe5h/WztCRqhzzRzi0UeiHrlzunnWFyv56CMh7AmtWyzBO1MPLRb9Mt\ne4DVxoXGNAUBHfZhIMWoQaGQZ+XY6pPT+vB2K5Cddd4FuiySCEWzhV8SXkA3\nWm1QQFgr/bxEQnZOdwp4H4vCtAJFUz9LL17bnINrgvZxabPENmVVTOZOeYlh\n1yZCfazN7hxTUGPcSXOR4Ug41q55DCnodnFm3PsCXU8fSGWe21Pbq11JpHfs\nZxPm\r\n=DlXk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD19zX4ODEt8A5CFnAuJEM0tQJRHkZpGFH9ZgL9+ykK/QIgTzijmnxKrceFmYZ4zjJX7lyerojhd2zsNRU+tlEUWJM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.0-useropenid_1552469877662_0.2923705260650493"},"_hasShrinkwrap":false},"0.12.55-alpha.1-gaone":{"name":"teambition-sdk","version":"0.12.55-alpha.1-gaone","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.1-gaone","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-FqLd4hjw6rgQwsYulaxsMy7eWjJ6Ze9x2SEz2b96v9SQlAcXavYWrMlMmCNzu+uGnBrk1PUmzHMFlBTim1skvQ==","shasum":"aef57f9d709e6c2c55cf2c052b397cc2eda78feb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.1-gaone.tgz","fileCount":431,"unpackedSize":902720,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJciNT5CRA9TVsSAnZWagAAsd8P/1antQAnI+0Dc82h2c91\ncAFV0Sa3+xH/5zKSfyYIqI5Obamn3h5keBTIePSJ5mbwOhWmcH7kcWK/wpeq\nEllcWgoFQGN5/rMp/w/B42PdGQ7pJgwUEGSuWkwgYt8XmIpmgaYLKCvzBEYQ\nHDLzPzTyahcjNXOv0AeD7SElFn83GiOYyVbdbR0dii7Oso+Q5cVdU9A6z/Pw\n69O7JoP6XV4ktSmVTg9azt44OMe5vb/fzSCtblYmzCtFlBkZWfEZPPbvSp89\nq9zXbNilJxbLQuCU7vID5vQ6DhfY54RzTraXBZNcpkCg/c28qfYHq/42Bgm1\nOM4KSWwwK8a1EwSbU1CzW9BzCDA2075FU9+2nUKxAUzGnZI6JFz7mdDgEtNB\nPChqNI/4NLRPtA025x3gO0qPruIoiBxH3VyfgN4NTCntfcvoa89x3fudPywH\nXhhaGXZPcL2Obwkl+nQYoBoD29nqnQj5XvxO0RXMrVu/5PGe1Mld8hhqLNm7\n0DcpmDqatJ2KYYFSukl0XLKvCQecGPD9sHd1oAAHPUYwXcfgdsTzDRvD/lFa\nVa66yrkr/I8B8TLFXwL7gGDdG/Bhz/8Yj5JS8+G72CGyBa276Grb+HV4raeD\nTPzDIy40HMyj1W9jNDEJX4mP4tk1WnLfpY9RM/VW+WwnAkZszMS6GZhsvQQK\nkJ0y\r\n=S+kJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCGpafsVu5p1eoWb5UX7zUSX5YE2Y3ZUQ38xFM3WpaJxQIgcL1QKQ/ZNSWeV26ljsg+APulDmlQ2RMo+vWG52F8aIc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.1-gaone_1552471289071_0.3097033274934242"},"_hasShrinkwrap":false},"0.12.55-alpha.2-idb":{"name":"teambition-sdk","version":"0.12.55-alpha.2-idb","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.2-idb","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-yAnmubuJJbiE8mQi+4DkWjnS9liJRzuCsER0nLgtNbGlR2BT9JMtyAHIk2Aa0sDZvxqkbW2ae6Cm0Glj+/VmTw==","shasum":"86f34034447bac92e915c1e16285aed2c31cdf9a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.2-idb.tgz","fileCount":431,"unpackedSize":902516,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJciNV/CRA9TVsSAnZWagAABF8P/RUnA3/fkRNfA2G9kooi\nlpfQxGKBqJL1amFngkOamdDMNP6z42N5bhW6DzCAcVQm9d/fNuuZa3LETjNZ\nCY7Kvs5Q8K9XKLxP/Ad88sMcQ6pFu1pRLvhDw0sp0PC3ej605IEMLXyJw3BY\n4lK08XIKTsoP3i21fAPzaW82mgqmGDq9FuTGjpeDIpDU0vvtintfi+qnT9Zx\nWOKAuBDluqrh7Kr/6cXkVuzVoZfaHbkh+i46QgV1gNJo48+DbhPjm4jmmzpG\nAEiU1Bw3PGudeDxnJ61spN1caXXurTuozUZEY4BE7EkfGyciP7/7wjcadGK2\nsJCPgfRrYgQU5TTYMwa/WzjwbYezxG1Le+VSSPvwCfSNWtXxag1ZL7zgw3dH\nbVw4yRpdLs31jHkuoOOkKa1iv35A6pI7EWDSBoIRnKcs8yPjrKLW7S8w0Ylo\niOONMv4B/maNSDx7eAnly8pjn/s3kjyUcmVhuOfjatKBvzznkxqsThA9ay//\nA15oaK7k13r4XkRwj41wDB4ebKbMvauHlF5rc8qCAWTFeMUzBQZIbecCdpET\nCLGC7+6WbkN0wcGR+H2GXtIStpRja+TBrwDoeKUQWGIvCN5zBrAlu2QnIx7b\nVlhSJkcIkoe8LruyAjmIfcA1fk2A2npPxiwEDykhue2CKMVYGLLlcVIC9P3J\nVV9H\r\n=5H1A\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBxEHiiSjsfjK+mdDgfeBm2RiDekU/kkZpW3NkdzYfjvAiEA/QP5XJJyivd6g0dZY8YWeS7KLn1FRIu7/njUH0ioSq4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.2-idb_1552471422784_0.4525088370499317"},"_hasShrinkwrap":false},"0.12.55-alpha.3-ga":{"name":"teambition-sdk","version":"0.12.55-alpha.3-ga","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.3-ga","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-h3R6yVIsPiSNmMuFXtsFxUDCzSzenfSDdwbcT6xAAtn9b2HqFumCkGaNuVqsLnJMoJQiVBqmXhLucyYt3Tytqg==","shasum":"87828a9adb8b9f557f83c4ca6dacc396cb06b036","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.3-ga.tgz","fileCount":431,"unpackedSize":904040,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJciPJdCRA9TVsSAnZWagAAX2EP/39dSNkaUnH++LoCGTpy\nWTMc7cNXo2G2FvFaB3WvGZPSI9cF+Iet8WlGaBicyC1n2d+RjrSCw/Y6W8AS\nLl9A4I/BdMF9RnM1v1B6PTKQ0/QVvLOpuZPcoxGAI4Y9retpyKtbrLEHzRD6\nw2xd5JsHodtRz3gJHW3h94NuPgWfREc//ZVgwpcqO3/co7VNKgYoJj166hbr\nv4Yj5zHzCmjuGkAaqenmdxmNMiGFNbAbLr+LL39LFI3+WD/P0Izpc6eAk1Z6\nSP3zsCVdw0cYWsZYhfw/7iy1d0/UWrNc82g7wl5/u06qUJnLmqTW22fjNums\nGbdjq/MFL3F4MNKX5KXYsGbI4o3rZjSjQZfJO02B2vKVMhPmI/VejU7Khatq\npFm5eiyvOxq/EVuMmnMY4cfUe2hekE2VJrQoCWLEk+EtFmMx4i4TW1wTIZZe\nxlLF1sxpdk1H4OhW0QbEnl5y86wsSH2Br49GLoah8fRhN93JMrEpF6rGfFHp\ngued/VKGT1bR/PLZSPAmULR6v6cMPAtHcYGXpTsnsmm8eX6vEi2uUAAszFw2\nVmWabsx4yQxg+guqqcEDmjZ5cCCglB5Ql8g6M+DWeQdgbkvr/zh+cgQqwTsl\nhqu2BTuSa0zm4HZunIurikRCrdDggpcp5QNznZ4T+wjPiFbvc1xPJfPAt10i\nV1y5\r\n=Q0dD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHqlJOtWpNJGqTWYe87kbVczlkMFrY1OjYthice6E0wlAiEAzIcNFz8lD7L6T/bY2t6KNadx1AewVDRubT7p1JsAwtE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.3-ga_1552478812591_0.36630343177090685"},"_hasShrinkwrap":false},"0.12.55-alpha.4-smartgroup":{"name":"teambition-sdk","version":"0.12.55-alpha.4-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.4-smartgroup","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-yJvYJfZfV8KgIkTVFmtb7AqJOp3pHm9Sn4+cAySc5+D2CzGljGkeZcqHv9jmXnEc9Q3VLxs8kUQK3xfGYF+S2Q==","shasum":"947344dabc72d459c006b3cb3aeb937df3840dd4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.4-smartgroup.tgz","fileCount":428,"unpackedSize":905785,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJciPOOCRA9TVsSAnZWagAAQiQP/2d9/Jzmt+F0POKWF6Ou\nhawTbGqooQJCSWV0LnulO36yDs9Ad6sRD3JxMo+odbPkGO23oqvsB49gqQS4\nc78B71D1GMUu+1GKd7I8mEHwLoO7Hg1+tR18+BNlshnINgEPzGCsslY2NgkJ\nO7LoTE5HGjGvBelW0ftNdHALzWE7cjh+BCoEz0OOZx434HrNBKnfDjHVTSGF\n4aktC+2gxDgjrglHj2N9y8TjGdG85sCNLsFlE7ESrcDQ2C4Vqj14xmbX5bD2\nmiSyk3BEWvgpGxLuOes/LjIlEsw9hnXt4KtQAfIXmUEQitf82gc5OXs5DKaB\nCEW93MI2qQslhenhhxXUIw9oLdyc2VXKFbcdZH2ne75oZXo8zm9jZYhviGby\nk6KKNpif8FTvFv6GSZbh7dnfLQy9D+/IikRQBJw9veaLXA62J5jBhR6zW/Lc\nsX7k0idKnADbLoWGPR7gK7V2KRXoDMXWgZ/B3koVpo6Y/2j0AeLMZjaQKRHD\nBMrmJ37l8yCsVivDO2WKRRJtUksAYZ15ZuLl9aYLUmANLtK4WabCqc3DsWhj\nQwkFXYuRwYCSa0PPTneaBigW5fw9ppsaaGfwh5HWB4VSZogxguK1LwERsZF3\nezSksC1Lsk/H7m85blsl1quu7Eud9UcKDdKwEfTdawjHXpfiExUKPpkc7mAM\nTKdw\r\n=TCyX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD6IOFQ99RIDy2R/t5KCD/5cvRvNZrAH+V0wDohybNPIAIgDfgPmFlYsoLmH/sN7Bt9oP4azVpw/Mj7WD5n04WNkRs="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.4-smartgroup_1552479117528_0.2989929017211064"},"_hasShrinkwrap":false},"0.12.55-alpha.5-dedupmapfn":{"name":"teambition-sdk","version":"0.12.55-alpha.5-dedupmapfn","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.5-dedupmapfn","_nodeVersion":"8.15.1","_npmVersion":"6.9.0","dist":{"integrity":"sha512-u6uEaldEn0H4LArCnoEh1Paqsg1NiV8r4zSucc+gO6QErNI3PWgG69zveqCB90S+jLdos2M/3x8tBCHD+MRBzg==","shasum":"c4030ae9c03a79e46fdf63e378aa24d0d2583b1f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.5-dedupmapfn.tgz","fileCount":428,"unpackedSize":904447,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcivcNCRA9TVsSAnZWagAA79IQAJMJIDRNkYhY4lixGm69\nhxNSTaTmRvG67caKuw1xDurmqH25xaXh8cYsVcuTMRVolnnLiu58UqO2dd1M\nf/8nyi35zPRxlZMQ9hHUd4/EqaKfV6VGeLSehkORdhTOdAhyULqbN7+xzleY\nAcS89o95Yk5MgyWjDhghg/FmzCPayD++84w05UZkkwbFR8+BoqRS4q1cEcdI\nV9mhZnGTM20fpO2SdpJkf0Sazhg/sMRJqya98IXbG3AcofgO+06yT8h0HLW4\nt+8S3GGy1zUC/aB1wVOTclDuS4J14/Rc9KXuwvnLCMGE+Ke9cplvRv6iWsDk\nVC4AWHWM2s0nZnIye56WmI06ovDbq9Ba7Os9tvZufGVcBIXCaY/Xjcz/d8JN\n2ziWlEWS0NQXNgEZ4v/C6b5VuxOLLl6Uoli8V3g31yadWr/Dtbgs32bKfEr8\nHEsQCc+EnmIk5AeCfU6eWzVSMMW9rfLqZ72P3TzD+wCCaEwsMKgnm11Uy4cB\nqz3lwX8dkzGCYQNWCtP7GqK0vnxmfue+wPFLoSZabNEv1M84/dLqWPlxPeIW\nRMS+j53aZE5z+VGZcwXsOKy8Pms7ADcmdyV7moCxl04KbubX12wpGfeZjQwT\nkgMSOT/iTSI7HSsytk9+ksl036wNY0tpB7dlYj8au1BOAuGCFT8zjxDFuMSO\niyvy\r\n=QQcc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJQlfWTsqmfhD3Are1IjdL5tmKAeiupMWKvfEjSTcg8gIhAKj/oD0rGmLph9U1L/auSXA2wTMALqDRsyjI3eWjkFUu"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.5-dedupmapfn_1552611084702_0.14560192148660867"},"_hasShrinkwrap":false},"0.12.55-alpha.6-gaone":{"name":"teambition-sdk","version":"0.12.55-alpha.6-gaone","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.6-gaone","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-yIj22auL/BgJqeDMmDJwmViCWw5n4blI3Q4H99FnDlxXeqAuvg1IWeCxJzYDXeV8CWztKUlwngzQee7qWVTzDw==","shasum":"f473f6c9d51fcbf2ead0126868591734d2e17341","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.6-gaone.tgz","fileCount":431,"unpackedSize":903174,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcix9jCRA9TVsSAnZWagAA8jQP/AtlT0EjDx/my6NEv6tq\nUW9QkChLvSuVFW6K/at2XyXDh+46DeyptjbnAsbG8yR+i+O5vbFoS6Cy/oYi\nheaKF78V+aUSv2E+L7uhbElFgT6r9wYaVru2X+fQ45KTleF7VEEeglySFlD3\nay6xJNq7CMU+mbTCrqcoBKqYtUJBYJcGnfT7dOCHkwlmG9L1zjT57Hp0VSR+\nPlDYe3St5t7xJnoaUbwl9JQ2uopZ13NdHlKVuzdQNsZqeSSzRkeZbk7MWXLh\n1IY2Tm62meqk9+ACe8sVfmkm2zcg/64JjTha8Op9FcKqqVrKiJX9sk/+XIgP\nrIwjclfJET64MSRL4njoLsN++gjgzBC/IB8Ws4KY1q6/SQsBG4zueLpvd3sf\nZKokToqaVe3V22uJm5H+QcFZoJZm2jxPu0dYulZIdymNsAm39qIqVDZo8OpV\nBy6reukkaCKqqKA+FzzmkRdDUQvL8ZS7XDN/zJgYxIK8JNYCJfZYNa1DOe0j\nQmGBTA8c2X36rPZNtbJaY7/EeXx+Mc5Yc0Yx+eC7XzShELtqIZeNWqACaFwu\nF7gi28Ra/ajoocwJxlIpajX8YrQ/uyS0vWXq1SavE7AtgbsJkYF1yY7Fa86m\ntc2afpdEkD+wGCaDNanEeRRv5ay0OUGY51cRrJa4G4zivNP9rY0OKgmo+NGv\n5ztX\r\n=w6bi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCAr5djUtXdVVaP8X4ufMuiWY8EFcYKKz+FM/4uv0oDuQIgd3MLYPCrWMBqszyV03bhEg2GC+qmMhXafPmW4t2iszc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.6-gaone_1552621410781_0.44308125555248257"},"_hasShrinkwrap":false},"0.12.55-alpha.7-projtag":{"name":"teambition-sdk","version":"0.12.55-alpha.7-projtag","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.7-projtag","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-yQyTGuWBZbqoi+X37HJLgyWQl5K4ZO6itOXl5bN1AUEpmQSoO9HIpE2CdFb9Q2go2n31K4MEcaLy1t1wB0Ozow==","shasum":"ccd1f211116f0b31054eb58177441cf8c62562cb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.7-projtag.tgz","fileCount":428,"unpackedSize":904625,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJciyUnCRA9TVsSAnZWagAArIwP/iHvEsfwe6NYUpT8uoGw\n2HwZMrGnmtAwAtCQE5sPXrTfHiTv3Tx+RAs9qcyWd2eDYimOKVPRXKrqtuU+\ngAYs4KsiFaqXkV0nT2MOSSRc/ZqcklQh+Hg4L568AxXHCs8t5e+NkzoAIroC\n1ZuP6XPzNKzTMJntl5PKY1vEeceEcCk37mPgN7/B2lR0OwTYcKFh+Xm4vP0r\nya2f25D7zprynSnfewoH5mH9C8n06bU5LH7pfr6Ldx1mAszuZSEyxKEiOiXl\nIRFOQeK3czxpphOZPyzMyxbGsnAbqhbZNYtpyklr+MwyIxg3sUqdh2ZDBV80\n8N0XfkXyEiwhSE197u3ZVh0GVG6izi1o8zAvk28UNwpqbh0/SYYw2n5NeNaV\nO/K3HfhQ73rL95Gx8iKDMKisil3N2tHnv+uA6dSxRTgkoxEJQAss4fiNBKtg\nTuns+SUqKDNRTtdmhRCIZUzTMJzRJ3SZbJH94Qi8AJC3Mc2ucKAlBNa0YZH7\nJp30hS8Y370dAuLySzWyrMLvWgmEHiJLcHZdLH9Y6uSipYO7pGGXYdzmqP9F\nhf5xIZPaVJovJc89zx9l+C3tw+lavPQkDYC5Llvex/2/cdYVzGd3oJKHvFFX\nvJOZkpuw2zCjg9lp5pYBocF7Jw3v30jBlli75WlFdn0lzg/uNo6z8LKs46CL\n1Yxg\r\n=zHXn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAxufs6egoQB3iJtk9GTSMytKKtB0I6poC2EmuavbtW6AiEA22JjL2kfNYmLwc9i1Cred4LW1JSxv3L2eOFV3Us4UX4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.7-projtag_1552622886854_0.508156603968597"},"_hasShrinkwrap":false},"0.12.55":{"name":"teambition-sdk","version":"0.12.55","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.55","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-FLI1xaqmo/Halw1h1bissXPlmKmYnXaIYn+i3CaETUN2pNhJ+DJ4bA94OZ/Uzc2R+LjyJ9FCSMWZBiEs2xWABg==","shasum":"53494c6e2ee4535036916471fb3ee64ae5699b5f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55.tgz","fileCount":428,"unpackedSize":904428,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJci0MACRA9TVsSAnZWagAAST4QAI7A6G2LmrvfTzmGsYGU\nUgsmaMcUxKbQSN43UovT3wJlhdUX3gv0qDGsQueoPqZnUTxm13bJ//DTM6sc\n6mB0KSJE+g/Ptb8GSZNkvvqmqDGf21mzSkP68g904FYuoWbQnvhWZkymDL+4\nCxRx7SnHd8syuWesAh0UKTkDFNk3AUiLunzJip0EF22yKKO5YbDOSWCGwami\nh71YfRjGljfr7kf3/QG8g1L6W+/WVUjqCgcHywOSKXPGRgUDHJuTeNnYufYw\nXr/M7bcDypbr4eftcwiwtkA5YbSFU3iLPekFGGVNKR4HVxz69N8EmrFYXFsE\nt0D1vE6CNOtJOpJhMLVmOTwGnxTyBKoJQGCpOTTK6AAamDrM83nddb7hdozz\nhBHX1oUOpKhAtIJy5vXiHUU2MnLSxMPvhz72KCpPyE8yXELp5NaXn+Izq50p\nmsJ8bIpCgG7uLNkHrFCSe4W+m7kK8y7QPoqZHXweiDeEtKc6hAOFhOAtSgwi\nnmgBHOs+lYBHGf/9n2MMpjepy7wZBitfjcfxe3z7mU+qxN7g8EMCFUReuVmS\nGW5gF0v+R3aa/tXl8++aorc02Sf+UA7vibNxzufBpvMwGBAWQUshlDE59zkj\nBbyqXki1Kj3hqY7HijbY+5Om1/g6PdRgtySWWKsW4lUxUoXz1f8gZKNWV5tw\n0an7\r\n=YKUY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFBHoEbZIvpZ+dohFqsG1YJ8hNzOwTysuAYeVX/1zZJYAiBwAk9Cy3nBYaZZyrOT++ykI0YVeJirzOiaHiExNdkEfg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55_1552630528008_0.4846283995408718"},"_hasShrinkwrap":false},"0.12.55-alpha.8-graphql":{"name":"teambition-sdk","version":"0.12.55-alpha.8-graphql","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.8-graphql","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-TzlnCGKwybJDzyRTjwm2lfYkr9StJBA6NCyMNaYmloHWHj3T5ghCis1+4v/RN3KRfAAx3g8TVw9GUA0ceHiKTA==","shasum":"32dd674f44282d7902cf5c83d478e16b93cd8c45","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.8-graphql.tgz","fileCount":428,"unpackedSize":906104,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJckf6rCRA9TVsSAnZWagAATy8QAJyZ4TfdAUfd2D+ukavg\nno41W4ry/MVrMQSLEHIMw3lMbmzmGbjnGBltbz9ELi/UHz4YxtzGsZSuaa1H\nBjC/diP3JDHb3oH8aspWx/qdK77mdi1q7WRpExL+mAlh5mBZj1lJ0dQ8M6x1\nqjjcLS2qP20QESNVKdDpLxqFU9dT8ER0iqv+Vxcd0Z1ykwxOpIiFS3B62nWk\nKZa8F6gPfch9BJrVZtNVF3/KyU0sSmIL6gWbX/pKrbp2l4p1vhhDWtNpR2yT\nLNJQtPTszQFCe2iP1rJfd2JrbHZF7ixGrIeA7CumQEj9L4LzxETm6D0IS55s\nNTL/wwN5ldWTcjrF282b5DT0cpsS9PV2n4EdeuAHTiLf55e+wXdUrVCzfgYr\nrjj0c17M9SVc1xz0OvKZUomNZYxwZgW4Iq65Nmr78vVj0GASZ0jASIXXgCgP\nkgqf24eIB4gTfbLoK8Gbf65c2zUsL/ug92d6+ByTbNRmhvRDQzJInVsiE1g7\nFDajVnoTdx8hoIN4Ytxfnc900pY8dAaC1OJrmBeqUsg+gcqssYtiSQAeMshz\noGmpLzks+UddME2SBOXGnv3NY/fJEqN/n0wNQL/cFnnhYBUR+exB6JPzuV1k\ndU+K7V3nGk/MLJCnaFkYIMrsxc8ciSLkYZukQpyYA/zNTusX0bBVEhHrw74w\nOZyO\r\n=eaUK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCeotQHDBGsuvmJaTgMo3Z+AkEQG2nblxH3wkuQaBQnOgIhAP7wWZgZ6bh/VwOW7GYfPiGfUR9+mJSKHXYM6qA+HQtz"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.8-graphql_1553071786282_0.3504388094087909"},"_hasShrinkwrap":false},"0.12.56-alpha.0-ga":{"name":"teambition-sdk","version":"0.12.56-alpha.0-ga","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.56-alpha.0-ga","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-wIc2qVjUS15kDq+27wqyktTM8eMFMiLNGuTPO1RkMqiUhg13yR1J6ubiePQV//A6HykT+yU//mDAhBPOHDyMuA==","shasum":"3fab6eeaac376e6fb91397ac1b571f581466c97b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.56-alpha.0-ga.tgz","fileCount":431,"unpackedSize":905883,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJckgC0CRA9TVsSAnZWagAAYtQP/A3KyAAIelPIalfoRpgT\nWfOAiNXGyLQjcZ//bVkBgfFcIpSbjZSXerA5Q3M42wnb0Yfx7IP9tV//HqBN\n1cD+UWwAHrg2fdKG7iBMaVFCdQ94RgwcuUUVJAUfToUzdl9GpVF/zOLmkGEm\ns9oX+lPOYfbwShYyvrrN7TlIUtTvmxSjQl16mYhqfMBaAtkzyVtAS34S45Ft\n/2ncylEHUqYT/uWECRxL8q4sFTSE49cwlWQXgjRT1eHeH3cLezy4OU/a8Xii\nYR6DvL9So+r9JmvW47Guww3wUcZ6//0yCNzSsV8CJFT9ThZWcROpbwGvb9ox\nRT3p85CbrOVSpQeMQN6nxeI0PxFlJ7CsAV65SJA6CmZ4VQeoEX16T2lu7X0H\nyLA1HJc7QFa6NBCTFyZKL/Pb67BRN3NPyWtkDAHrI0bOnerjFvKdMzKjcsbC\nUeYmq9HK1mLHJksBc5Gnes3ozJtJV/o2Mk2DULqOIYUS71TN8AX4GF9tQ5v7\neMZT9uY4q+eFB+jLbfVxjjQGpexyKWHAa1Zjaj9fkAxaQGVxoU+VqhVqh5/x\n238pe4nJeiRAUTnVbuxNOpYuwSDuVuJJfK6TgSgQgRVv3DaBEcpb6JWzVRqH\ntSG243oKiwZpSJHTey21gSYb1QxiAfQmsFIFVuo0HHQbuFKNHkGnHRpaA1Qu\nBHJ0\r\n=Rs8+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCm7h3aTuYsV2pjiNVryqREQxHY4RgC2tNucwp7TzII6QIhALYKVS4MDJpKDR82ISf9/tNDnrjbIbbveRAyLH/K5jDT"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.56-alpha.0-ga_1553072307947_0.6309589514458778"},"_hasShrinkwrap":false},"0.12.55-alpha.9-projtag":{"name":"teambition-sdk","version":"0.12.55-alpha.9-projtag","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.9-projtag","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-cwSdf+vKg3qqhGJy9mAYnIMuz2AmAcHyJiN0TJfxByRoJFXxebQBn+q6ejC4hUIl5tBjODGiGz7PjYVxWq2zRw==","shasum":"20f3b8ab6201e5981287ce1487055536100622da","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.9-projtag.tgz","fileCount":428,"unpackedSize":906286,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJckgH4CRA9TVsSAnZWagAABuYP/2iuDU7merH8K9Qx7FVR\nXr5+jvLylA6SsVu5/fElf/bhQppPopBDNmGSbfjPksYKExIQBUGUhc32p5Lz\nwFiI6ygUG6ktDLsxozDLluloZji27FO/GjvtK/RdLblRWFLdpIHinZV076lL\nG+qgvFEoIDJa7oIzh0jidmD3jZDR/Jie/ugYKb9WmA29FJv9hRC2zJswY2HB\ngyn2Fu42xTplElIUgEbPjlacQc21M5h9LiNTa2p0tA2OCgqWHMmuPdaiJXos\nayLzVUWzFhqjTC99jTC+MoHZj1UE2vd/B04saCyRnKd0WiX6m+oGpq7ULnSR\nzw3dLdx1ixJXFwKAAsFuBcbvQz9FblNmXdXUBngTapf7Cr5wv0mrAn2Sd8uG\nmPjSrKCiwTNvub57HnwOyRrT0t/IYWMSkdAro6ibhXoiADREhwfxFr9dv2ax\nLxXZwG2+XU/gvogh5aroYbw4nfipC3CMD3oqEyrg3wR0JhNN7cxq0vE5FTR1\n/tZxNhRNOQIVbkq92DFr7fUf3K+0sWkj5PKR9ixqTlDZG3kcCHJcAEqiYPMo\nvI16uRWRnX/l5TYzaryL97v079Cr0pjOb99H7dwqIGAF7pEarFyLg42djTeP\nyb01cv3obAM8n4zy9BtgMs5iJ+luM7a4UYiBuOcgRAplNMJBqeyO2K3it5jv\n1Qwp\r\n=2Cg5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGIFsgHUvIJRSzhMXLOuEuIaCkJUpjpq5Uqfh3SA9ktYAiBFsuMKlVYzH0zhMVVepoHb8u1dHCChUpd3r7oeU/cCTw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.9-projtag_1553072632177_0.37764529123317536"},"_hasShrinkwrap":false},"0.12.55-alpha.10-useropenid":{"name":"teambition-sdk","version":"0.12.55-alpha.10-useropenid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.10-useropenid","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-FBoixXQTLl+tShZiRl2Ex2N7JQ4JayEhBnh6UsF2X1KcDlNVAaxPkTaN4qRoIoOCwDolZA5t7pg3ZGRT4LKiZw==","shasum":"1665d62c6461bd02cc86e95eba09f2fc4490b67d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.10-useropenid.tgz","fileCount":428,"unpackedSize":906499,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJckgQjCRA9TVsSAnZWagAAN8oP/1gtFoXGj3kZ5Pv+P21C\nrtNTdgr/kZfnU8iG0yNfW3FIZJ2jR9v7g3Tz7IPcNVuxP+X5Loln/iRbizUr\nBxj/aUyMxmj3gD5DCHgii9xZxiwUUqfwc5AOtO5StVkp5DvLOUMnDBWkhvit\nBgOJfCgW6IiiVYfc0DjNALKXW4I+ez+pYVGHmiUHKt0yp9YOKthW2Ekvh+E7\nHkQtYQAHVysTa9OgMR0ioGROTwxLoA1nzK3TdnnfssbzTx59i1+DGwwsHB/o\nOYtLJInO2wZ3yfFlJb8L1Jfp71njlA5qC4Sg9Zp245LBif0HiJWeZwLolDoi\nt3Ggbhf0DWBDmOhMb142YFX6kBgrEOI946wHwJngB5mt5p5/nXQSYkUyw44p\nORlA0KWYtbEX7iRFbPOPTdD/RwOFhc/DwAz3NeAhXdXRvHDK2JTxIAqd6X6C\nUNC+MJS+aje+G5VXhfSvKs8kekxDMmjHQebgzfUZ7exZ4B0sVgCGaiFI9c5p\nmWaD8DFqqgiyyxq6OWZIeX8KC8B1HuMQ3B20AQFaLlqn4XYQo3zJH/vCfGsi\npBP8NVBlo+p9irQFpg2evG0l1Sic4RFx9RtnOCQc6oBcYnLvBq7RmHSHZLMS\nXzOpH3pLrPB7U0YDNmsWSgBZ2e0/N+pbkpAPe48n1QlXWJVmhcya9fVM5uKe\nc6Et\r\n=cZUT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF4wjaWcbuvQx0TKbXFvDlPrEX4NA7THqAqf+q1LY7JVAiEA+Z9PbFYgnvskKMTe1AJ3YuJTnZ821hN7RlSt3qOLXjU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.10-useropenid_1553073186385_0.315487403113462"},"_hasShrinkwrap":false},"0.12.55-alpha.11-idb":{"name":"teambition-sdk","version":"0.12.55-alpha.11-idb","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.11-idb","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-/xY+j1Aqez+2xL8QaPkzrXcYYwmPEbekmZzsV8UYzgKLD/pCTyvmc36AI/kTN4qtjDMBKK0Da0WwTg6CH1LvDw==","shasum":"25107bbe31f2214c2822bb7fbefe76c20c5464c0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.11-idb.tgz","fileCount":431,"unpackedSize":904561,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJckgb6CRA9TVsSAnZWagAAKFoP/0SipCJvA2Tgm3qEPnd+\nsD14+TaeXaqajynHOnH3ZL6jPlzJr83npyQRX6xi8bsb0Gw0s7AFtoc6szCx\nTcjRyN8YsEuvCbzKjK6r2KIXDISEjYPyavCTGV/iid0MskboC+ugpWwIxY7B\nrAqpMdonNH48obRki6L0VB3rv7Z8nRHK9TEmT4vyWBnPQ6BHlBuxObuXP3JY\nq08jw1+sJBlGZJFbn9fHDs8Z1D1vahBrglDZAGkaGmof7+xNe8UccOLN7yb4\n3SbjJ8aHE+MA6odt4aKrCdNQgQsXq8tXiXKvnPV5D9HiaNYB6wFCyT0HoJQu\nCYonHBTscKPMp0sDm2/cyN+cT4n26W5YlCMADx8/c3McGeSTgWC1xeyzLNDC\n1txkXxDTP82tp6nLzNpUFVGfZHyw3jz6ChknnrV+6k65h/MAhfzFEKMEVOdF\nIe9qsuU17RODBkmZnAP9AMLcQrgqUq4sC38U9aqJmza6fmgW9XxOCwl5o4oq\nFriiOk6ZOYpTnosvtwH8o72r6jIIi5EadfVp2ionacSpIgl7KyyLRtnClHsU\naoc3RfhACA9qMwsOobS1xm0UfmuTifJLk+hOmaXSO/Czx45c7+35d+uMKjpw\nlCXSe/2nnzyyVKZMX1NwSDitKmyxpmsEiVW7piGZ7k/Zf7PbwBbmBgX3kzjp\nZFjH\r\n=oyPJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGnrryjqa04kBNPiDB31tOysGHOc99X6Jm5YegqEh3d3AiADJ5U4VsxAjsrqEKfeVSpI1VJzhaUYbfPp1SpWwiyrBw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.11-idb_1553073913614_0.9059048652778727"},"_hasShrinkwrap":false},"0.12.55-alpha.12-smartgroup":{"name":"teambition-sdk","version":"0.12.55-alpha.12-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.12-smartgroup","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-jAdNtlCQBnIqwXGWhQeAP34EUH1m+4PtsoAC6YXweVAT3yAKyiq6+RopCujz8MIOdxYhjafEImFSMTVZLDJ4aQ==","shasum":"b12b717b94d52ad456c93b21bb8880dbbe4b578f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.12-smartgroup.tgz","fileCount":431,"unpackedSize":905891,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJckgf0CRA9TVsSAnZWagAAO0oQAKLju1BbJ2gX3wpqjkpg\nCfGgn465M3yulR6DTTBVpB299Fi8q2u34DaeYxUIdkA52cuMMjEpC5SFAWM2\niL4k8ZoU0jPx3mOzPCfLVk//2biW7xfeKVd88CQADpLiaNzGR7ccst5CD4qX\n1SjKqrmVaRqOz+UT+Rq2nIwDMM1ElvUzImManJu6toxPniF2vsOIvZkMUcCh\nAOfc0BveitMV7+UXlqVb2nazjdCqVlZlKSyH6eCwhr7pEGdKoXy1HvTUVS8H\nXTkccI5DhK2zUDmLLBge7eisKukFInCnBnw6zLFitNB0r1QjiKDGXAxApgY/\ngm9xum7lsWiXMzuHyRzwTVHyNgaWzuwZRmsQHvzs9NNpXXxUixHioqTBCFD3\nBTLnBmhHVgb52f/AQFWA5aafkPq8b8XMUUJ18iZDBsXBVCL7+zkPTQCb2i0s\nNMeLwEi8FuZgc9/BapnpA2MxGMfhV2IX9FaIjyetMjdtDl8nzjc9FjAJQ4wy\n9crpMrdVS2ieoEzCbXyRlxQn8pj5TfQtU4BDawjh2tUK6AgEbrkUGoyW1aYi\ndBgxn+CjgDojnPRqDMClKZKR4EJiXa23Lt4QqCenwoyllfqo7AjdLxyvPQ1V\naro7OiocW0t7DkDNL9EV1z+EnOlQdOLO++ctNu502I/X13RFmXOCxLZp7cBc\nbaXz\r\n=nW+r\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD7zRdgNnlFiOmP8xT6ztwjnvtHIqDTzx6s4EBg2EG5EQIgB8aRlKz2plOzjo7W4hpo5YWGG11EFGatMxXE1Es0lSI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.12-smartgroup_1553074163393_0.954591037722009"},"_hasShrinkwrap":false},"0.12.56-alpha.1-taskprivilege":{"name":"teambition-sdk","version":"0.12.56-alpha.1-taskprivilege","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.56-alpha.1-taskprivilege","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-w+R1ufTp/n8iXQzhQ9m0IbKbUwEXSuCvc5BURazAcd2dxmQFsXtGmu+hWVNOaihYkzv6RPfbRbF+6iYbO7lczQ==","shasum":"d666d861d151f4e3f64cacf3d1a1790bc435a11e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.56-alpha.1-taskprivilege.tgz","fileCount":434,"unpackedSize":908922,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJck2wWCRA9TVsSAnZWagAAIbYP/0eENo3WDl3alKP5/+8r\nIgI+H4PbRzlgkZcCF7VXVtjLDOF/943psp6Iq9+RFU/dP8x3bdmINSPCFvd/\nbFKtdbd6n2ZVOuPrulMqhE0sEJFmEL8vYz/IV1G4SH1EZLxc43dsLol5liBo\n1NDsxUxjbBEU8op7JEgbmYKePEOExLDElyArvERWorM1yfO+S5XT1ofMgcbA\nSb91T8efuTPOTntMjuhdT7wTOMU/lWK84mrDhqYGf4bKDJqptrW/N/gsvIYw\nJX4XJwE1dDHHNVeFvbOqnb7IdwPlAfHXb4ucjxlW9SmguREE2bfHgTj/Reym\n0LXKUGjFWk885Zx3BXlAKThizz6/s93R/tw8rKBwCAHPZNzZjlYFWngKlOqM\nt1rDMZXWrsahwifSe4gWZiTV0sgwjuxrHkeygWS/Tvpqm4Di3MPiqJ4F6yL1\nfG7gyBHKF1dMcthTtIdCNndQ1DLlje6IJOPCksl967kCDTfc5ai2m1L+oTp6\nk1ijzdxjg5KuHtC+VC7L43WPoLpevPVavyYTWYZycrYMmci7snVFuHuiYNoh\nL7ecPwjGv2p1oL6MvnWE7dekMxD3Y01cjFfdZM8/KQ2cgmpAq+JMRK9b/vbv\nRdVAYalP87sIciggWQ7K6/m1gegSYUeAvC039S3KUK+3RM2GWTRZoqT2KT2H\nFTfI\r\n=2KFd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF95OvT3kPZBu3UmgojkgY9MTIZ0S8ejjHfh8LpNVV59AiA9dZsGxVcSD+gvvwGj2olh0XxFIsk6uv1F5AENBuErmw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.56-alpha.1-taskprivilege_1553165334183_0.24925533641846132"},"_hasShrinkwrap":false},"0.12.56-alpha.2-project":{"name":"teambition-sdk","version":"0.12.56-alpha.2-project","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.56-alpha.2-project","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-+w1qbXCJJ6Wl/AEmgUTTtZCIjGTmJYsL6kaM6Xk/MCjpz9PzDBfJb08j4HLNiHYn7ayBdo0wGwBl25HzZGWWmw==","shasum":"fa6c6e05fbc95dbe134de8c434e288710ee1bb59","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.56-alpha.2-project.tgz","fileCount":431,"unpackedSize":906342,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJclGJjCRA9TVsSAnZWagAAaC4P/j8GynzX0hnvXQ2+xWy3\nbqWJyjgREOD+HxuNymLHvGhXHkCSVJL4lR3uHj9MXPSbGJr/gFa1sFyFhvZ8\n8b2ObSpHEGX0cQ5oru2MyFsMRvlTLeHb6X3Phufr6iLee8dl4x3ggf4acq8U\nQ5+XlGkFBRVl0r1z2Z7P5qLT5FL1eYOdwRNpMvhKyRX6nY0zyPbHg1SbHNML\nGuaV1jsc0fK7WWKryR/Pl0jRVTq3Dd+OihirYnm82z6qkNbjT5twJJHuHyL+\nf+9qbjVfZpTzZMBSd1EwB18nHIU9FuBg8S0vSM1B6hgR83EJ1ZqGTQ7Dufpq\n1w+DOtLcyHmxoqkoYK3HvawtQ+prhOUFNL0qgW6lZ4wOX8rdCRcVvHxoKKjG\nz5d/6hQh9zseDwkGREUEo2XC/tqKU0jbcb6go909tgz1b3dkHw+3qHqfsm0d\navgKLIzcPWw65k71GioWbJqY65fcoo7IHL97zrXxVqkn5tz6YKxbBxbnnJG+\nLixAVaVT47gd5n0zPSEdMVa9dR3JIerXRHx6CXkTiT6HW1vXdWFVerWtyUtS\nwZnE6iVud1AHTOw4KYftPwrmgSPvp5CVP2urtVCp/vcGF3zI8aoQKOMl/l/0\nlUoPNED6ibd6h6Tjn4saXE5L/kUN0KF75FaZkIje9Zo8xdF8UlEaZnIwQoMm\n+4Fq\r\n=CuiW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICJ6wJgTqkAkQ3mqv9WfplcI3/jFfGpwSHulZaGKBCmXAiBqFTqF/+yBkBS/bY4eDVhxbbSGkgfAd+KyarSrC9/vPQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.56-alpha.2-project_1553228386101_0.04753331863381338"},"_hasShrinkwrap":false},"0.12.56-alpha.3-gaone":{"name":"teambition-sdk","version":"0.12.56-alpha.3-gaone","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.56-alpha.3-gaone","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-oLS49VkOdMan42fTSOqO4OkWLxjuPc+s6BL7iNznclXcdjGxg/IcPYH4TCtDyic4NsgmuCeQPbexD3RYUk1HVg==","shasum":"862d98134c2cf4a473c41d8c27e4e250b0941969","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.56-alpha.3-gaone.tgz","fileCount":431,"unpackedSize":906340,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcmIR6CRA9TVsSAnZWagAAFL8QAI2LfraEIwbzrq2S65n+\nkmDQyuQwIYnAqQo0113cMfGlgNvG+zhThtLUs+fTayPKwYHiWz8BWeDaQ1lC\nTYrZISKiRVr6t9M15jv3AZEAgrRRx65LjbFkF3066qtnI1UCpWLQPw04JPhf\nW0SyVpDXAz94C1Tcf6Dg4yMGm3T9FSgm6AlI+WRHXEKq+fuT31quSaRktfqn\n4gEZm9ycw95K1Eehf2yd/LNDE+hBgTMm2ln0Kqmum4jwjht13YtfcWgrfBQ2\nnLRJ+jTy1HizwjCArFTAvAwP3L05eMQqnMHoxVPh53YhtYqSR28F5rjLlEjc\nv9VwrLDQM0j89t0LWchyLLyO1e+NYweNd4+8DECfjQfX3MyWmH7k8G+WxPP8\ntvqWSbTOVN/pJQ7zRchINm4NzBTwgGjXz38mNRZ2M5LgMVT7brgFets5BXFY\nLmut2jsoGFTdnv89Vb5C0GHWB9PhC9LJ96aWbTyeORcnUe1Q2YxTIRJuF8Bk\nbG6S0rW+W4Uu0QlSxRJc9hBQiiEXHreuECqQmSWQJBuzxJTc3zJ48HmFU942\nzISMYXmiz6igtzuTv9x4EKYYvV5dwI4hly3rse1FeHtAhiBvRAEA3Fiae9XF\nBPh/2DdPJ3aFfWmmMR5cdsv91MoBfigmDf+X5ovmYAZvWPfpx9338tasE6Yg\n36Ia\r\n=qs1x\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE87Kbs3YntIFl6Hm0MSfAV/Jbg9kzPeImODO/rjpXNiAiB2WJLsAhJt063c7i3Rx5UCfS9QwwkDUp5s83L79KNgsA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.56-alpha.3-gaone_1553499257726_0.3540290738026546"},"_hasShrinkwrap":false},"0.12.55-alpha.13-aone":{"name":"teambition-sdk","version":"0.12.55-alpha.13-aone","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.55-alpha.13-aone","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-i2E8dVDaIgO9c7sk9MOrkwQlgpIcehCNYEr2ICTTBf/iVOqY5G5jlDpQFRKZpwsiyorIdmtyWaRVrKAkidPBBQ==","shasum":"3f362e03b656b32ec5c5572d3188ad2d7fd5aa93","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.55-alpha.13-aone.tgz","fileCount":428,"unpackedSize":905113,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcmIpzCRA9TVsSAnZWagAAZDIP/ja3uf97XE/Gfk07rxy8\npD4yc05ebM3FXCJI6LJn1E2mKszL+3JmFZ+HB5o04L05AakVbhk390WFOwZZ\nzEIOIQRpZY8PZ1v7mMbWEJ8BYJY4WuAP7Jh+6uCbPappUbQC+BT1z6uPtwVi\nRawAxAkqRNXdYZwCl/4J7ownmg82ug9Hf7NkT5mtTYKHiKq9W2VPtLXPnA1x\n5e9Eu8PDBqoPaSl472TvuNM5XJ4FX9tLynlJezULV8R8tzewM1QXzm/iKo3e\nDV1pSO9fTnZLMWVRHGSDnT9053VCra9Eq5hOvLJFWzlASD/Kpvu7lge/xaKH\nLvEKSZvqEVMydwypJE5i5WXrEW9SBKoNUwwxdWPyyave3Wdp3S4iOcwnidfs\nRMw2ZeCrRXqSDmswoFdWSn9/QBAy6Hdyr/rFa22VFjEa/bk5U8xJ35Z4TWpd\njEJ7Nsy371UJmcbochTuaZglYsjDHx1w2vBEn6U81J+uRfhjo4mkvGU8XkNv\nDBjfVFbl77P5V0A1VZ7/atazEeUsi1KtAd+F49pARKA8+qQ01z79LlpAbTQg\n+E/JphQnI0QKuGZPY4VRaZMx6c41ZWf5f32lBV0VZbpYvWvAT+qM6zkyKvo0\n46nGJzTKaQNkaoJZNh6QCzLr9O2M4OjL3ZA3QeQlAcqnmaG6T8l48zhgknDG\n4pef\r\n=21H5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCjX2c6NMlI5EdgfLm6tel3jx9k4I4EsKVgPU7om2LjOwIgKqoZ//VCFsFzeRj6niDAG2c53abe7vBfMl0LS8wjnuU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.55-alpha.13-aone_1553500786265_0.01595356551409033"},"_hasShrinkwrap":false},"0.12.56-alpha.4-sfcpaddingcustomfield":{"name":"teambition-sdk","version":"0.12.56-alpha.4-sfcpaddingcustomfield","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.56-alpha.4-sfcpaddingcustomfield","_npmVersion":"6.4.1","_nodeVersion":"8.15.1","_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"dist":{"integrity":"sha512-4X6TNaOapHKesGHofx0E/RFGach0yPRsULtTn4ixHrAw1YzsyeciVppekOgpKlwvdCcOIta5S6dCs90kQhCcJg==","shasum":"e9dcccd2d5b2f9d9a19982b4d5fcc8a2a6189055","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.56-alpha.4-sfcpaddingcustomfield.tgz","fileCount":431,"unpackedSize":907603,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcof8sCRA9TVsSAnZWagAABBAP/RrsLMUGpjwe58tAAttX\n0yrOG+/PxrkoLG/t5iw+QxRKZ9Hs+RVL8uiiCCE8xTLDn2GJRx5P5FEIiy7R\nIRxMFJLGmgpOb5rEioiPLtzQgvJ8QYCzJgFkXEVPdQlGfizYtyYzm1KUBbMK\njrF5srrYkSk7sdOyV2TymJcUpX/WDrgL9ScZOZi4y3Ws1C4cUnhiEqimN7hm\nIauKydEIJF5Wegw1VUQN3S8+HNIkOXEYcVvQUn29lywLzp/mVkpiasl7M1xF\nYhSMydqyVsj/nNcRTRspHFw7mXUL9ptE6gTOl18pNEdG8FD2iuSgS7qe3xCe\nQBZobYaz36Gzn6hWd/ssHE1QCJqFag9y9QgIo1RI+TIT0R3aEzCpgyBLnmaD\nHyiDyygDHnA5Jfkf3dXLQOvAT1cFhPsUyZyJL+3K6Fq683SEpWT3Y+w6sSDX\nS0YkRL/+up/g7Kkw03hB7d3+0hVCJqddRf4LpcatN8asjb45A65CseSkpE52\n73bVU/ce7WJWHCRzL8Rx4AuFdZhsgT9qGSoO7pGiqTiamNL5bPVIOU3aVSYl\nMeY/IwTFVRxpxwl4CPskG6rK4sCbVRZ3PGPpRAATky+ysfSAJYJHiJvfeVBk\nIgIoK+rFPH8KNd6R1/Bdj9M8qDZ68bBYEEwTyOZqXwD5UgzjVGSzffS9TDI7\nSwtq\r\n=VInV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFoAxhRfA/XsYI3Hj4NCrGfVfQ19KapF7pToaLVcpt6ZAiBGfjDvzrEfrmjl+yf8OMniog9aCC9R84/Qf+2sExwB/A=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.56-alpha.4-sfcpaddingcustomfield_1554120491587_0.6113128541544279"},"_hasShrinkwrap":false},"0.12.56-alpha.5-sfcpaddingcustomfield":{"name":"teambition-sdk","version":"0.12.56-alpha.5-sfcpaddingcustomfield","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.56-alpha.5-sfcpaddingcustomfield","_npmVersion":"6.4.1","_nodeVersion":"8.15.1","_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"dist":{"integrity":"sha512-1Gar/lLK5Lw/g6dzHdfuzb0/fmiZpBNMxj+UrnARaqBA5Twr22SYRBIIIPLlMFPjdlCf6LDGepm0X+3SOmko0A==","shasum":"a40269c7b203c96433b9d3ef52c513abb4feb551","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.56-alpha.5-sfcpaddingcustomfield.tgz","fileCount":431,"unpackedSize":908796,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcot1RCRA9TVsSAnZWagAAu9gQAJu4dvhJr99EH9BnAyvx\ndxHLHOiMkfIB+l6D4IJr1n7mZAVUouvkCPxDxbi0T+CCxfKglOYYNgOpfOz+\nAby/lOb3gKxhdMzULPoAiGUjQorHZEmHUoW/sB3gMD4Y+5qyBcjScJznA+py\n4PXgvHCDzJM7oBEiypjuAMcYr/jOLljlzPMjU7qHdo5JcfTJJWSfHptXIEps\nkR1/bwCFAqnW+lJdoyTSw5EvvR+nWyE8mWLDCeB9f8gBd7J+l7t0wkI4I7bS\nOwYcRJ2NPIKyyLBZdGhkyGA13eMp9pdf/DIe0FlyXFsHcbu1BcVemZ/wiC9x\ntPUxYcHBNCbU5kKOEU3G9LP7P8Z7HiQSp2E0rqXKe8aVCAS/9EmIB5jFF/kL\n8SdeS64v1+YOOPp8djFe5SmLv5KJHGDXKmsMkFxttafzueT5XkIAzJ9EVCRk\npxbdNt7e9qzQKp0mVb4RawD2UENdBxkkIKj9zRhnb0BfRSH0UlF+gKSk9NX+\n5qKpQItUb/AgzXw/cog+Ko1swzx1sognyyC4IFzOJ2dgHTCqhd1Xx87NsR59\nE1jTJ00G3VnE1xKK7NdotbjgV7LjQquJLaFpYKkvEvL2siG1chNViI+3VdaQ\nlnFE5s32xNeDj2QQLJZvXJMyvFbxlaGzqJQl73iAluB5ZtVkhTsHWEC6T2g1\nNR03\r\n=4kuP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID2/SFGJNUhBSKfD7N30i/olU8xI3IlL+JrXna7hI1HBAiEAhjDbBBpfri7UPXFoDpD3kHJzhGXVHLAdUGmwEUMVrsA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.56-alpha.5-sfcpaddingcustomfield_1554177360709_0.8455139890501"},"_hasShrinkwrap":false},"0.12.56-alpha.6-sfcpaddingcustomfield":{"name":"teambition-sdk","version":"0.12.56-alpha.6-sfcpaddingcustomfield","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.56-alpha.6-sfcpaddingcustomfield","_npmVersion":"6.4.1","_nodeVersion":"8.15.1","_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"dist":{"integrity":"sha512-kWrsc7WMIFXHHPO8DiEkVgfVjVhKJa0vhZoVQzj1ULlTX6bd3d+dyG7nl+BK7mo5GJHR2nGI1d+vC2BV3BtMxQ==","shasum":"55ba1cec86362d702650cbf7213a84bfc89daa33","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.56-alpha.6-sfcpaddingcustomfield.tgz","fileCount":431,"unpackedSize":910065,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcpD+CCRA9TVsSAnZWagAACpIP+QHcXrMC1cEDknaI9hOL\nSxQ3MoKAU7/XCowrkj6eDu2xEBTOCtsF+7jsRYMzp2sHQO6Niwq1ScMfavXG\nwcZ1Ylqt+/2NQ1GPLQeePgsJN7TZB/6F//g8WTs4vlQgCwSejVkyBgEGBXfO\nPVogG0mWWMDWjgECvTbL3WvmfJo/lmn/ckf43q7W1tViWWWXm5I9qQ2iVMZm\nVhySZs/sfr5qWh7Bez1B3zfl1wksxPztz1iZ8FrgcvprpacoPXogxPyJMPE4\ngA6WuFkfZZvvAf8RyP36oi+YNdwZVpu9mozvzAKp5FC2vr7NKFxMcXNVCO84\nkRyCCrB4BpPf1dtchnavBWntxzkHE+uQZC/ZTC7M3q234/VNbDbvddRUl/H/\nl0D3VslTqFCM/56Hzmy2yLxsjvkSupa/r1L4PDOAp1PIzO5MiUyDvr1fjr3f\nDzwtEvnhBWUTDJRwtordsMP3lbyYJG6FZ5aGOy/3vDFrjhEe38ZqKyTpTPuF\nZ0oYVd9sj0oA6w2jaoD2gztqRvAggplRaQhJSq40YO57k6vtbF+IWtJqRBaZ\nSpwRWtMQOCDOlewcf+xJsfoyip6M2G/U8Oop/0Qih9GMwDkDpMmsyq+LN7/L\nrrmY8kiwhfsTPC3ehRJYU4tzPTFyBoB2vRvyO8aWpRakLlIihIQubuLNHe/3\njLQR\r\n=oIh0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFvsxsKammWszdArfOrDrK7omb6Ujy3Z4DNplFFe2kZIAiEAylsijP10njA03Mi973bM+6zz71CWdrmngPU4Ls6fZN4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.56-alpha.6-sfcpaddingcustomfield_1554268033785_0.5135733653389816"},"_hasShrinkwrap":false},"0.12.56":{"name":"teambition-sdk","version":"0.12.56","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.56","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-R1y97/21S3SzAcoqOhumNbBdj/jlj38kw1zd47eeuCzjxhCareo39f+fOM5L/4SQ19BKsFT0LOV5PoSlI5336g==","shasum":"77cb8352a05550b3eb7f3dd0973805680e7bd3ea","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.56.tgz","fileCount":434,"unpackedSize":909520,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcpF+aCRA9TVsSAnZWagAAdxsP/33R6GjYgB0iKdrL3hma\n7QXgt5nAJQZP8AA4PTRT6wdBswXqAKb30ztc0blcp0tAJlrNj0yToIJdVUnn\nbIAPclCfFaVcD3fwhGcU8ttZJbW5WMcddKMpf1xRoPzLBz+bkswnzqyzkCpY\nrKxOf80a70YCAyU8KTJv9EqdorAG73/Nq2h37B3gC0O4Tu2ECffujMp1O7Vl\nO6rZ12UbFOg7Q8HyCmwmBrM7XVzj6GaiAmQnOKWZETS/AHJcb9WAdZUuBtqU\nZ/DhcQ4qoPaQruPK+fWPe9BawJEHfDHrhIuG94IumCotevxv2HNO68aTc5LX\nnXJmC7B0LqbBir4nSJphr1cU2j+fhK/fEvF8h4CxCtysWEkW8CpzP4Ws9E9q\nl04XqcZfCvWKu3pSIAQlENvxwXmCs+EIBQzERmNXbheDh9ivXqtYza7nwBk/\n42zdzvKZ5NoXfPRNRl50J///S1tof5tA5hp7U+KVQyrm2G2VJDsKdneiEikx\nAe6s7+9z+tI04Y9qmDL85qia1TrjR6P5JAO+cryQg2e+HXaCkbhRPyH0S4NB\n3kkQ9QgoXUD/bv3kmq2jQCstFPba7edPY4DDekoZI3XB4ZsIOnqj4Iw9eaaG\nuq6rtFcSVq3P16SQ94Dk9SqzsB/OurGeUZWv0YdBmCJbK0cuTulIafMnhwXU\nMnxb\r\n=l7iQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEA2as6py3+l+8BLFnf0ZDbQulGjxbGJGA2WlAIVYjWuAiEA2+inP9/xyI6RDDau7jPvJXPIX4c0j2PSHlNR0uBxdd4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.56_1554276249230_0.137313104938652"},"_hasShrinkwrap":false},"0.12.57-alpha.0-consumerid":{"name":"teambition-sdk","version":"0.12.57-alpha.0-consumerid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.57-alpha.0-consumerid","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-sTZaIqkAfmS7z+mhtzH5ONFjHLkjPKPWQN+uezGqRTW5wQJnf3iI7DtgsGD9T74DthgDdVKf3XUxDD+ZJV5Efg==","shasum":"400154cb2b0da94e65ebbffe02777e8cfea902b2","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.57-alpha.0-consumerid.tgz","fileCount":434,"unpackedSize":910037,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcpGTACRA9TVsSAnZWagAAHWMP/jwBrZ77YKPyW011ymnh\n+z7A6E6eIyvDIO9OWaIv68D1moU51/RRVdYLinCP24K0GzqZ8R5on+atTGRf\niqBKzj/yXAHQu2Us8IO65KuMFXwG5TWZEoFtyxgukPN+zh7YgfEVqGBT2uit\nBu0NutTFB9Wtev2+frK+SfasWL+z1xsoN82IXf2bkx10cDVuvCX5Jr84+8jx\nBrWBjCXcNuTfIihUjS8OmGa8dlj2PqFvyVZuStcLLE9dbDMfYLES3OWKwFR8\nFvMn0jtW9uMZKYOtKEXpUfwFyFQEW3ShjAsYljMq/w5KriDylEmG1fIphhkz\nPl7PwhGiUwJhELgdxHZdGv8uLYQpRNL5i93whIJszVT/k2y2Z15HFCNhA5nz\n1yZbfVcruXDZ0mRLudc1FZjJ6xrg0j/Gt3F1nGlfPPnqfsMfbFx9H+Q7AmdZ\nZjImb8yQi3lnbkSmHuyB0yFJbg1tYRYVeSTwpltS50PG6AMV+aPYpG6DVSl+\nRTCk7ScZ4IvFq9PZK3zmeDn/Bf8SSQhgO4/TU9P4jj2ZItso9MVh/ALW5Pic\naZgHXueedjhfMULk6RZGVY3DjNX2JRpaz+OtGDNbntWb499JnPlEcDhU0HLc\nsasLJSMiecFnvWqm/OMTubgnQKmUkRQOh4T7DR01wRNVLAisAWmmJB0of4BF\nPl7M\r\n=E/x3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCrZxvSu5uKFSf4s5RRry1Hkp2qkIN2p07g2MHA0150nAIgfqKulacoizc+rRhAgK9jUl/QYPxxDrWJtNC9HDHOYHg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.57-alpha.0-consumerid_1554277567900_0.966143809977593"},"_hasShrinkwrap":false},"0.12.56-alpha.7-sfcf":{"name":"teambition-sdk","version":"0.12.56-alpha.7-sfcf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.56-alpha.7-sfcf","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-aGajpeazkE6Az/ELD/Di7Ep0V8lfa7ufbzMIjDx5bY09AyfLYycX71Xq4gXcJswaIAFegbBY471rDpgSLY/GFg==","shasum":"c7af512ba6bac3f69a114d57f6061ab472de1caa","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.56-alpha.7-sfcf.tgz","fileCount":431,"unpackedSize":910048,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcqrprCRA9TVsSAnZWagAAGsUP/1wmP5fZIXlAUqUgBbbW\nRXqpljTnv5h+1gQFI+dYN4ztDQ+Vp601LdYcrDpF/fHqSEjWBPJp2J46mN3R\nEcsXLSzBU9fROSWnCzGZ3kd04SBOb634es8m6rc5CYLgkHNqWVx1wvM4r2EG\nszjbsAW0WwICtOK/5UmqVNhFwM2dTXEbUB/UR0g0049vgfMbzUMj2RPoFfo2\nIv6ogTZ3JzL3+hUk7dSDM1CXB+RDsPQx5fUnC/5RHT9jknpAhIA2tgrfCkEo\n8Rs8WTj34lMNptfBQ0WrTAqDZcGN/0wRtqibedqrHCJ2cp4kA2hbFsG1FzM7\n6CmZoTb4aCiT2wbdIvaApueVYiy7MpBpEQ7s3pxhCKbEWKYxvUYVwUNM8YNn\ns1cwotJJWZ1u52J8V/9FCsp5kk9t+Z/YCuzH0wUlJ58Vm4epXKMXdaJpa7jF\nUJ/9ucgk3IMI0xxM6Lqqo1qCrOFJc4Mdu2bFtT7PAqVEBNr/c9SBtCCcHrVP\n8ZM0xz98RDIvnGa56BjLhPq5l+vQRqsgH1aIH67Wcj8zUcxRBiLyfQRa8ekx\n6e7pEqy0k2tUh9OGNpvQCCI1P6s06O9Rh3S/PhfkMxgmn3NeTS246J149WjB\n2tw8sgv69v/Z/A0DKGHq0ozN9faydSgGq1pKuK7NJTbxNbFfVtX00IS+Mwum\njZIW\r\n=LjKx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDTarHmg0AQ8N70WpXQwrb8n/Pgn2hCPKokaIigMRvw0QIgZgKctc11nzUr5S3nfYZj/30sL3lqeoGT77O2TiP2oLc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.56-alpha.7-sfcf_1554692714159_0.44311752128697734"},"_hasShrinkwrap":false},"0.12.57":{"name":"teambition-sdk","version":"0.12.57","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.57","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-BMyGginv2+2ZSzUoSaZzP0ntg9TOWmw/nXJjXoRP0x+Xdu6xS1LauOFXAgFa+d5t2qSCjjfn+ttYhW+UkI6hvw==","shasum":"52e287bfdd68024c7839742011fa9f5972efc5dc","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.57.tgz","fileCount":434,"unpackedSize":913683,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcqvLMCRA9TVsSAnZWagAAxocQAI9ShdL09pyPC0h8rdgG\nWavgONyW2T7+f0dmlaYhK9fSFyjhuLVYSuAhtmnTerRwoPy0GIpCwQlh14YT\nBXE/pHPD6pO2LPvQG/9Ix1kAkKYM1VzwgVcCoWglcWKZ7Jw5KE5hQDWtHaJm\nUutE+kMMDJBwpfbeTWBan7KlkXH4NsM2k2x2JUB+knyOoejNlqXbKS7OBEgB\n3It9Aefk0KgnlQn/DBfIYlZUou86bks5YWe5SL622mQ4wrsdaRldzPepm1rR\ns6syQZOUe941xF2WLcNrGuzJ4E1Pe73Njs6xBGWyBaYLQWtB8NxZAOEbPamy\n1kjPV8He2l3cXyiDvJ5V7Aro6CdYLMfdeZpj5DSwM4Dtc1teeXQX3LbT2X7U\nNu+9R4udGc/0GfYKIBw7j8k7PsVfCQvGkKQ4ot6+dwJPLg82LoxwLZuosUh1\nBH0dkyw0sq4iuWirOSETE945XK7BrMToo6gIoNE5Ee1M9cOIJxPD31t/LV/4\nizmDstsPTuitpihjUJ4B6lDTRMFQ6De6WC87LrFQLv3OZBmxxDjI3Yk+c9yu\nT8TcZZqyt81QJl+gl6OTzHXHczcHHv6eik44PtQSvEmp6avRZFIRPyo9TwEt\nSlG6IcZtIwK20H5cpKhGIWqvliLbhdt+mlcpbO+ROH6o6P1PqhS1KdXJzURu\nSDT7\r\n=WwTn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHiRvHRM79e4NlsQj11n5gRABTExWKKshzqBn+bkwwLNAiBQAgD0Mu87El9lW2wQHrm32lYgXt+z3e3X4KOtX32DJg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.57_1554707147472_0.40000493895165623"},"_hasShrinkwrap":false},"0.12.56-alpha.8-ptagvis":{"name":"teambition-sdk","version":"0.12.56-alpha.8-ptagvis","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.56-alpha.8-ptagvis","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-QDEi7CQbj58Lc/Q6ljdp7ak65awxDFPJM0DDjk+EuRNU/xCuPuzN+9MhfEYkxXTDlLgUvA6WZ/tOcjae0HX/bg==","shasum":"71dfad62843f559371fae416315e2af4f4f0d07b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.56-alpha.8-ptagvis.tgz","fileCount":431,"unpackedSize":910307,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcrGahCRA9TVsSAnZWagAAeNEP/RTaatTtWACfhvBCAFm2\nu32/0mR8Z3i0cxP6ubzBYi9K8ilfBMd3gAvliZ+QCR4Ql2Af4UYbTgwQWyXK\nCZTl8AQ1SuH9G4OgN66VoWWSrK8Mif65rvbZQ8kvCFQXdaNTNdoUMV1UpCnH\nI0p/QMOxR3DAXPxZtRkYYDEAzbVfQ94U/dvdVxcFju0+tekMuPhuNDwsSLGz\nAMNmHkDhppBIDY/K2BZaqx+nnahipJtHsAHCzZtqJelvmUAraVcgZaYZYeV/\n65y1OaWA2rmhe0fzqPO3PCSRC5FB1Ljnk8qxpu5MQRUiGBeBulcE71Jk+4iQ\nh/FGABrXE6D6F8CGzt/2VZU1dUfJ0V0SStprGt1mRNI7uMwXFg6SU7DqAQKN\nBdyI5O4zs9IdpnkFM95s+BSK5vkqhWpFvGpFgr+t5xwAaEUL7rsIKN8NJfed\nABCwL2KoAGokihMV7sJ5fUGKtuiRGxlygFBkYBNrDDVQqFdfx0L+y5zKLikk\nUlCBRL6XYJFDqrYOyjmC8LDkhqm7G9nQGC1dt6/xwg9lPYgxs+DduyPmp9ro\nLMsxEkiWJtHfO01x+cG10b/7LNRhySxXKaXHXZfzJ8yNPAXWbYIArgUJ8cJG\nDfyHQ0zei05dUgKDnu3yRaHwDsxQGcwLMf/ZLc/YBTYV2MMXzP/cr//9Ao2P\nMAUv\r\n=AUGs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDq1+PhWwsgJ3quIg96CbJG+0x2sMKd51o8bmGlcsGEJwIgXj5DPp9F0PkA8uOWVCPq6x0qGth1AtozCd7BdRnD4+M="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.56-alpha.8-ptagvis_1554802337082_0.11230107295861069"},"_hasShrinkwrap":false},"0.12.58-alpha.0-ptagvis":{"name":"teambition-sdk","version":"0.12.58-alpha.0-ptagvis","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.58-alpha.0-ptagvis","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-z8rEzZJcHKVCu8BbgcO0et68WIxgGzVIb772IhXHTu2c/RKVAFfFtoo8xWsZBBeXF62kQRyUGCbjap/UhMOQKw==","shasum":"e5fa1c18d3f848861495bdd3ba68284f48873ca5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.58-alpha.0-ptagvis.tgz","fileCount":434,"unpackedSize":913955,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcrvb9CRA9TVsSAnZWagAAMfEP/2KlrQQonI7bAiWjJoag\nghUI+PIzWG8yabN5/ouD9a4mCGATXBOPjEyIeuN45Gg0fFybVRik5nDHWlPr\ncNpbrZjZpP6mk8gVnVx9N+1vwdqLYT2gHsIfvj0gb3ohiFUQEDzahwtW68pq\nrLVRd5OD48DFeeLi++AdikSrwmn3KWoFT8SXuUksJUONLHph+2O14JdBPRc3\nDmJYOZ09IoqNv3bjgcpPB9xQvl17rPnLZVB/g2dXUnRiocpfluxQnUOE0R7U\n+ZA0QtYHHW9eKdCwd+m5x+6gZEF6C83F//Cq/SMP3auq39wLJteM9/gYb9r7\n5C84qBmAqfDydCClMtTOBpwgx1a7KwPSjBqqM7h+Fpetn++EuZN7QC1yojcw\nflFxv6SiL60NGsTy7PRPeuU6KA7S8TSk+2kXKAEjXjv0tM+Fri3bkNqkaQKM\nzUrx5vt0TOgzkdKLMFtmCoFfaaajRfkfoNy3Vz+JJhUkx5m3W96y3O36W6wv\nfOg4Osb3vc+x8qAXujKZQ4nIp0JiS6mCH4+CAgZRo9V8hjFKPe853Efnhtnk\n775n3ZSVRv/Nbs089KP/QtFsWwcu+p9QjggmTAspk9eOfoBQkXpr8ZLVY1XD\ndlIDNdzbAdifu28gCYTng1EzuFe1UM4CGi+BygjwBYvcaSWGstXWn5hcJwuu\nTWkh\r\n=snC0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFRs12AccGRnNMQfEqrjsen21oSWOuvWeALNFmxKO2LTAiEAn/LwB7OlXYe3k/GFnvrC3P18lnBpH3HDT8hZgmzdMHw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.58-alpha.0-ptagvis_1554970364900_0.6753073367501485"},"_hasShrinkwrap":false},"0.12.58":{"name":"teambition-sdk","version":"0.12.58","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.58","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-gwgKnF3bw9N2GI/WHGfK0h0UnyRbuHKHZvpPWOLujYrTTWMpq6QXRLTo4V4Y8ljveBtyixccRKIdEWz5TQKcqQ==","shasum":"cf9bc131d3be8bdf42c377c7a7898c12f96a0f36","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.58.tgz","fileCount":434,"unpackedSize":913939,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJctAU0CRA9TVsSAnZWagAACdwP/0ulA6cIZgS9iQ02FbCZ\ngF8U5pdE5oLXJsdx69f2tR67qDYdUSAo+ToZSinudOghRLnnTeV3KFPsb42H\nCGCkt7WEg9qsa6fj4cDeYDqNbVyAtmo0lceer94ofCgig+bV8R7crg5ucCWN\nOBM+m71PPz3M/NctcAJjxD1NiVq/eiSjz0g7yO+BGdwMGiNQwGl7s84W0VFI\nj0m9alfPVCeP67bu7+sk6Q4mopvjs0UWLrJ3IIxsxsVPMydvHp9jpwRQ71Sl\nPcvoapRGmy7Ni+WwIUffhNCNxb6bDqqUWUSi+7vYNLh1s3r2F+67xY52dnuD\nIBbHAkMNYCNp3JgjsYL6A6TxBCggSxMzTRcGfA8oTKF5mPer/qY7F8T/31n8\nB6j/sXzQaK0+x+1+nONj7hCp5RGpfFsyuRP0vOSDPgMLnlCh4He1u+sLt6HJ\ngh9xv/NbqMOc3Sc1xjtVAc9yzazvgocy/dhLGARtEOgYkiEruVgY68B9KkDt\nxLbjOiN5jHDsqS11SdHr+65420BUuZv7C88a4N7EXyOdNwl4CPy4tpbQZbZF\nuXt4CxEkz3BAJkjBtf0L9NeF1NLTDEEVaIfbUBgFHIqbM/125pf3ScmqNN4G\nUjXCGW5skAlmr8BeIcdC9l8P+J8t9mgPPCO/9ydmNAl1ZV3FifvOChX/gD0f\nKepf\r\n=3uE+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDcDKlti7oqxsTiGwM4EFZuyfq3DGK3CmATX8wsBWQluAiEAx2HI+uhWnefQV9GDAjWH+IxyI2ANmE8kNzPWTy9xjDE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.58_1555301683605_0.9624114737824401"},"_hasShrinkwrap":false},"0.12.59-alpha.0-sfroleids":{"name":"teambition-sdk","version":"0.12.59-alpha.0-sfroleids","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.59-alpha.0-sfroleids","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-1LxSF6ggw8XlHjPJiFWns3LqSoTVh2QZ2oK5++rahkzVYIyNiWELdUZpqBP8jzSh2O6Bq7CUlkCG0ucflNpfPw==","shasum":"9fd4a8fa746b3d24446bafe79923b05c6627a70a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.59-alpha.0-sfroleids.tgz","fileCount":434,"unpackedSize":914349,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJctvwVCRA9TVsSAnZWagAA59MQAISxbZH9lDW3O7tVe7tp\nzW9TzQxKvIFgLz7zTgBPtnN/3x4yiVG0GkHCRh1p17WWd9urDcUNg99iKWwz\nHgjwBSy7WzW7hrzhNzAWlQ99VU00wUUNqgT08wphU+Y+iOny/wUikj2Z/9LQ\najZw/V/aKMeBymDENfBhcU5NTTAkdvVh20Z+6ceW9OKcsvYeWYy9aKvATba8\nxlQPJfT6iUJ2BBVPNQdOmZspRJz4d+lKVBQz/Madiee0wkSEbkd4qqjrXhUa\nhmSB2dvQ/yQ2KCMw0JDc1lJEdWH9pAg1I+dq2hIzTzkZXld2b2mi2QGqaYEJ\n+KeCfK28wLn2e7RjJyDs/Rje9C+KAnWnkzQXGxqqEP58XGMsf2LJpEQ/6GbP\n5Rfo97V+0n2Y9jg27FawIx1LavqRY5wEkMF/hESq4KqitpuX9SP20bDrfor6\nKlcKNttMtrIfmo2PLatheIsqh4n7UH3sf1116DpKuTC5yBT2t1W2/7r/6Akd\nD9p9i5S4XIbk2IBvolYmSf5iJM86ORKCa4YBd68LunCcYjp/zzXAhn8KDB/3\nsWgL+NwbTYh8HTP0okvSIwQQSy4Spe8R8zEw+e9npFa5cM4Fh9nYx9T2plG1\ngQTBGEdk2fvlW/pgv2frNpZO0yHKHS+2HJ9ui/A+H+lxa90yAGSFXcsSkivj\niHHZ\r\n=a/cD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDDpMG2EdKmI8IyHGGDOAt6zbU6Y9NnqezusjdBwtIWlAiByQ9LOiZU0kaFfM4hzd8YB0Xq22tRSjgXlmRSdlRRGrA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.59-alpha.0-sfroleids_1555495957036_0.7354782397574096"},"_hasShrinkwrap":false},"0.12.59-alpha.1-sfroleids":{"name":"teambition-sdk","version":"0.12.59-alpha.1-sfroleids","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.59-alpha.1-sfroleids","_nodeVersion":"8.11.4","_npmVersion":"6.8.0","dist":{"integrity":"sha512-Wx7GCvew969uX+H67oYu8D5tL610qhgn0KDvOdfUq+nu7jxOVsKbMpdYwF4NatudQo5LoTEsV+MO1RSYTzVluQ==","shasum":"f3f42420bce9a7febf8b443463990eed30a5ff50","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.59-alpha.1-sfroleids.tgz","fileCount":434,"unpackedSize":914325,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcuBRjCRA9TVsSAnZWagAAf+oQAIb456gPiFWmqQqz38co\n2D0pZD1zK9gmfDNLLe+5QR1OYl4Cdc1c4UcJcrHAdDVHHGkE1I0vVxCboLwR\niIJ0y9E5fW/FWRaDOHCdGmnRe+uOjLU8f6tNZa+i9vx+rXeYaL48zqz5wnV1\nuPWohnYgFxShI3FsDiuYb36OpdokY2E9IeO2cuK1t9/c31DsnWiuDUHMoH5g\nB4LBPmwx+9bNpipX+1Uvx0TNgta8UvuDUgw0i0gqMmuw/pIoroz3Z3R6NdjM\nYSY6YckgRDUfE3q+v8Jf1bDKwU0rsv9uoOKv0CbGHVtm0TyX/VDVKj6HLPE3\nlrUpoxXRNzARbynna3CIFnqG3DuwXH8m0JhOzo2Z+/FvvLqH7is5fLwUfdgF\n8Qo1brj6b3p0kh7q+6qJqiaGyxNKPShTH6g5lKShJq+01fY/v8VzlAG4tBFM\nPp1/7v7plEPN8+G/yOQL57URBeDuedjQuAgHLJJPdOz4J8+iIV7ErVi0ILaQ\nrzWLksziqtAsia/scn/WnZgNb2IpOwVu2ROE/aOpgoc2Hxt/l37mcdaP9Oo4\nZeWIv5pEgvT4M/yso7/P3cuyir4We0GTFYM2Vr2YwIHIN+7/cMUqzokjyClo\nxppt30RPw2zm1BeL+Ed1eiYbCfmpNzDTejt2OSnJoKq2bsPAf1N8VH99uteY\nNCob\r\n=y0Tj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDq9VoqTI/JYd5LxgGED4UE7VziR0HWwr1bp9uhB7+8nQIgWXEZ/532Mq57dpiPLecIGqE8d7J4soRclP5D79f6MBk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.59-alpha.1-sfroleids_1555567715239_0.7551603565663108"},"_hasShrinkwrap":false},"0.12.59-alpha.2-taskwithtaskflowstatus":{"name":"teambition-sdk","version":"0.12.59-alpha.2-taskwithtaskflowstatus","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.59-alpha.2-taskwithtaskflowstatus","_npmVersion":"6.4.1","_nodeVersion":"8.15.1","_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"dist":{"integrity":"sha512-tJQMV6Cy/lkmcY9k+dclps/anEF7xmq0VBy9zcep3npzS/PhMeGTbperJ2gQVUE4TwXlZK4le9blhAx3r3J6eQ==","shasum":"6e76ac3657be1de99498ea7bffa550d1c24eed69","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.59-alpha.2-taskwithtaskflowstatus.tgz","fileCount":434,"unpackedSize":914881,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcwn7QCRA9TVsSAnZWagAA31YQAIKxIloqHFnkY3aaqwW6\nM2HshF1vfI3UPc4cqWM9u6Y2gmpBcvUJeKBqNWZkZkFJwAhmLeQ+r8XevjCC\nPZ1xma7rykQxLeJsCV4K8xYgNcLBPecuBlVVge/QEZBlFz9ngPT8yVR00z+9\nrNV6wSdgLZLm8Eg1mPM5LpdNK8HCaOz73EyoQSTjX2hVzOHLuLiQwQFw9yt6\nvus/uvsnDtgX1dc4jefYJpWFQAYrxMMTwn9pF6HQ5FV3fnQlhu5VDIPgkvWX\nfXxoKQ74rhomJlwc8b2168AmbD5Drgmea6k0gbem7DCYY2asHZcXLoOo13QP\nHoPlridQCVYGNejR2UNMhYykJiKk3PYVaTZgKVGMdJH53Bo8PzYIYb1bWJoT\nCzT48rXsNTXuuPWZBh6oFNQO4Fz8vswtnENtA/Duz6q6HLiU4O4EQe8uARdY\nqonR/K84ROj2SdryG5Ahx75/+EsvtdmUs0Add331+iBuERG8ozZ+d9dOOlol\nQQpsD+eU1yRdC5Q4Ux93WqLfE2YDeu2ONv13s6AM5ZVQUoBikBKeypsdFq7v\n8M1KskGez9+HWtT5B95llQ0XcQIvDXXQYNYjHSC1YM5MJV8GzkFZ5mXZ6dp0\nirbQJnWVvZo6BbJpKSvbwqaYSd+T3Kn2RlhjMLOWv1MF0SAFPiBjmOUAycAl\npN4H\r\n=arAO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLP6XdDUthoDMHLaHg27IdchRoUnPJZagz7hqmg7BzbgIgRSLNkzO2fw/OrydFx6x973GPO8KmApahmItMxwVfzHE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.59-alpha.2-taskwithtaskflowstatus_1556250319766_0.8679794300344275"},"_hasShrinkwrap":false},"0.12.59-alpha.3-pcount":{"name":"teambition-sdk","version":"0.12.59-alpha.3-pcount","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.59-alpha.3-pcount","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-JD0WY4bFK1+0PSzYLbvqX+HUXMPQx/g2kL18rQF5dnq0d8rYuiHepA+wIZCLdJOOv45mw2HPkUslKq978nL9Cg==","shasum":"cc9b2bb1a007a9a3d8fc0176c284c40ae191f7d9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.59-alpha.3-pcount.tgz","fileCount":434,"unpackedSize":914198,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcz4ZJCRA9TVsSAnZWagAA7LcP/RzNe6Q4QSfA2KhnFkI1\nw3Wu5tjzDg9LxeCs4vGWUngRO6sosas7XLC+Q/6ScntaGQwFXyT0mN6r4dAH\nmJtjoW+3biE6CvQjA1fwnlotqpeZVnEKCu+INeyYvZkBqbTnE3KuT4Kwkrfc\nbXvQOE3Pzz6yhEM4aqOTx8TdhpOtlTtvkr2p2TzT8Rlz7Rk6NHJwPXgBGXuU\n21/aslYX41C1uf9yfLSljNN17HPDTQaykCpWx/YoZar3WWAybGe9fHr47iEY\ncx0bosgre0dMj3MlMm+EeZMHV1Wu16ybFfsAFz56tQOlrKbwXQpDMkdqtFmu\nen/HwgLLav5CRODyyUSLnq9wEoFzXGy5iSSZWpaVeFDiTJ3SYLp5J5nHqNbD\n5UJ947PDcoNn3hqUrwUepzM5jssej9A5LVxFuocclVBeXnmS3NGwvvhq1gpv\n8dTKljLTZdWVrj4XQF6rp3sPC7+BSVYuNFjdDyZhaRbD6oK2iCRSjaNRiEYy\nuKEfqflMyO37XldfGsmw9v8LCM51vqGeRGWcIitDwqrhlGnex8hxy4eDf5KQ\ndBZ5/+C8G53S3P59lZng4ryCuimnygQaJNWiSzyZWfROxNtYi54bmnFBMlyi\nmRoyXNzJ3ZRNLr5nuOMnbvDelnEUmAQ8ofJRlGCXQCbIxhryl2Ggk4iAOegu\nLceQ\r\n=MPMX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD6Z49WDF7M+OO8fnG6PelGPP4EpeFqPTRzehNmDi80QQIgfSwKIEIixb6mHl8jX3Ry/LZOCB2J4jArOJRB354pxwk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.59-alpha.3-pcount_1557104201120_0.01297511878444313"},"_hasShrinkwrap":false},"0.12.59-alpha.4-pcount":{"name":"teambition-sdk","version":"0.12.59-alpha.4-pcount","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.59-alpha.4-pcount","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-lKN47LsZy6yJoa/BL3U91Td7Dp+9UCmgSLb4RiVUx6vo5TtBlJZPBcCvFcy7I9Qocwq3+ridXj8si7WL90vV/g==","shasum":"0f4df857c03af30b827d301eab06e94c4eafaad1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.59-alpha.4-pcount.tgz","fileCount":434,"unpackedSize":914060,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0Um1CRA9TVsSAnZWagAAym0P/iXdP7Jk1NctlLYg07Ve\neUayCWryojdfSPD5JNwP+TKvntEeARA2yHj8AE4JuX/d8ZuMqkQa6/o86mxx\nYoQsSFC6VY4ADDUN/AKkCxAbMBuZNXCAjXi8bu0EAhWYWbj/dYHy9l1Rtg0T\nunVpGvGk28uyoen1EmdRFZ0vkoeh8eL9VHOLeYIr2Zj7xMemHpdnoSXES47k\nvO2fiyusdSuMKfQ/sdTiJVla4g8L9+IB1vyKqoGOE5zapcNs7LWRTHvq4Xr+\nNku8pYhaCppJAWFfDlo/di9pj7lgNloKU812PlRqhQtABPBQrlgjmcX4ugQQ\np5px+HiQFKDMfY9AKrWak1UjzZ5M/lPhW1JRWT0y69vn/Wsl1f1bQZ3iAJVg\nZu2hm0gMFktr5nFWoWjX5EDu6UPodeqc6Mp7eFrEzcbDj/Yh6K1OzkQgsqPl\np4hTG8BqcKFszemisbZ7KBYEgdIP2L7shZ/VlFU7Kgfsmo2NzxH+wJghZ3vd\nqTUivI0l4MQBX2BDmrSoRMl762zvUeFFFQfj/tBWnPMlofLeSUyJVKJzHP07\n17dWixgi4p5d/DDFLsMn84uaxz7ehgfTw7ofJR7MHaXW7aSAucjrOmcGqhMf\nF3QbAyf0zlPHL0BT2YNI9BCX8sRvj0AplylwUpGGGgNKc05XAUHZWj+vABWI\n0yla\r\n=M0L9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD+39Fx9P/BoQFMSBHeTTxTIjSYnRyY/Ysj1fWkl1E78gIgbVMbdFdppv+4NHxsrsDiObCPHuOjf0kSuT5uL7ELFCg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.59-alpha.4-pcount_1557219764860_0.14966516589788692"},"_hasShrinkwrap":false},"0.12.59-alpha.5-currprojcount":{"name":"teambition-sdk","version":"0.12.59-alpha.5-currprojcount","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.59-alpha.5-currprojcount","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-WmX581Jh5K54aXBmvsr+AVDSY1FDAFUfugk/44N6i2AIhDYhxHAKMPYpouCJCAte4/UXtVQx/N4X34eVoMgD4A==","shasum":"f92dea09b69c9ef73f73018aa9f043295e07ed0a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.59-alpha.5-currprojcount.tgz","fileCount":434,"unpackedSize":915118,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0k+6CRA9TVsSAnZWagAAATIP+QH4teAt3lcFCzYJasv9\n28dmGZulw3Ry0IZtZm0RbhVQnORva5TuZ2YbDJpDutQihHrHBjYgP5EHngq+\nvPwged59vakoTvuu3Ubsjx1/W4KSZiNyU0SxHrP008q/ne9/ThOF2Q9NR33a\ncqApVcVOUJl+NkgmGBaZDOGFzLpm63KACFRnCUNn9+kudikYLRPlWhFIMR/H\nQ42dBTNIUVAAHyIzyGHs8PamlYV/Jneq9HwHPFLnxZwr4CJMe5RF0+Tc1glv\n4YzxBgz34PrpuUhfMkhpIn5Wxi8BdmkXgkgO+Xk0lQ/kDbJDciLDVociCyp4\nZwhhUIsy3hU0Sk7yjX3gL9SWC3wJlsMnqFeHMIzWKHvZiJQLaRQYv42vZ/mT\nk6Mjy0OqUdCrrICGUgKdDR3NYjfoK5N4P7okZV3wKvDvnA0RlIqwuu+k9TBs\nybwhCxNlo3xx0prKws6dnEHjOu1T7qckQ78vTkoT7FiXRZZDxuf7P38e7omL\nAJxiEwX5Q4p63jgFkqJuJgrQ2UaF6bb6HOzTEVJfzsMKlrRc5n8y2T06kTEc\n1DsD415x1Ean+/oZUem/hs9Z4nEq49XJ3SlFUaI5ErT+Je/hKF6iGy7WLR3U\n1B8oc/WyGt7W05gPt9SkJ9vKyxtUvGjkUpAnRZi4pupUei2yiqLtc8AsFGrS\nFCUS\r\n=D1VO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEKxJLyfJSgzbg0QntvY6to+KeRRaURqDDYSbOjuqg8hAiA+E9/dPwOhCqV2o3Owyz/g6QOAnIH6ePvHR9+E5DmiqQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.59-alpha.5-currprojcount_1557286841022_0.47867286616911"},"_hasShrinkwrap":false},"0.12.59-beta.0-ga":{"name":"teambition-sdk","version":"0.12.59-beta.0-ga","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.59-beta.0-ga","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-Y0zSb896rHJv8Qxkrh/MLUOu+8EAXtwCbP2QBjHBjQZmiFGHQmXkKRAVVOzLPtMxfeK02+vH9Zy1Gaw1SmESDQ==","shasum":"1cb3d5d4c2faad8b3dea657bd859b843a1660af4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.59-beta.0-ga.tgz","fileCount":434,"unpackedSize":915474,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0lHaCRA9TVsSAnZWagAAgM8P/igOIfkdrmaPBqQ57kCI\nvl7/I7resyENya59SI0mQUMYNuzMSCbfElIIS47Dowu2CEmzK5vVCKNMFryX\n3r2VQRRZnct0m+xnwwsrRO7p/S3p8aIP/G4+q4m1hmlVnA6dv0RuBIQGFxtM\n7ZPzM4yQ6DhXvRSBf00ceE+fAnLgjhSydRH7sLW73V6UVbqUji8/0UQiJRwV\nJTNiWVqH04ngCNiX8av9tfgvtRwk/s3J53HwYoO42c1zes6mIKdWQZaO/K2w\nbMFlbU8i6WjH8O7QOp8Kjt/dpBhhglj+VuYY3KxCEmdu53eLato8uT0E8nby\n0iyzgA/dXCUYmcedlfiAFdLZ66IFH8uTh7in6vHPn22R7bWvQ/FWgQF+Izyp\n97wd+zdxJcpaSvofs/rxBb/qspBDA+tiaqOLYrmiQNTu4/mAMRYWceywbVMw\nLQqkYkzAoH2r4rIOo3dZJ1XgxA5XhCnHcSoiF68hUlzG2wXrIKNDrZ1Onrj9\nKwYNW69soYSe52+Siu9Jt9eVpLPtZHK5uehhZR9wmLzneGytelYXm+hFwQzc\nlMGcwUlY1uHpkgN9Y/Uk67FnSiw7AjZRuUT01Om3Z6FoAK7EQ2vTsTzAPDuy\n6mCYxebMID8F9GNbQtbkXRTGd971JAsTPGHSXYyuGYb7MwEqOc3X8cupQiho\nKvVS\r\n=RLR6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEixEtpST52pHLN2h0bYYmNAexZ3lCMBQ0s1zxp48+1/AiEAjwJNw4uc8shQkPx6iyRl1z3/jrg3nhD9vMaTJ9VPx7M="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.59-beta.0-ga_1557287385530_0.6277424091020471"},"_hasShrinkwrap":false},"0.12.59-alpha.6-pcount":{"name":"teambition-sdk","version":"0.12.59-alpha.6-pcount","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.59-alpha.6-pcount","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-Q6T/Ou4EoFb4xQRnkcMnoBXDGNmjxkcgkZrv+vWAA/5QwVwU6qw4ZhhwsSn5pGVxCFs47JgVxn2o6qx5pyuprA==","shasum":"0fd1f1a89a167ae3da66e1e8f4090be0c30879c7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.59-alpha.6-pcount.tgz","fileCount":434,"unpackedSize":914971,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0oGeCRA9TVsSAnZWagAA8WcP/0EnSXIxI7IeVrsmNIq1\n0Nk8/KFtSowGjLp5Zs5ihcHFZ7Y27c41SCPPIwIcQK0zO6G3JbpCOhuDcqjo\n0ZTYsY8MWYqg+wm8monvEwjIEMLn4A8e8uDI+DQIR/gYAKeObgh2Ur6Ne1Cx\nAt9K/OjqmA41DdtTXYZ2dxQOLmBJx1XGs0QS+naY9BGt+njWcWj5RfzaqlsF\n4wF++PZjvIYtNZRcFNq6HoD8JpQ/XQFDh8RXj6kSECBYcW5H6gjZtqxR6zIA\nQlqp0GOJK7fYqHaFkNDLkUKscQIBmOtv/EhfZdS8G+Hpl7r+c/FgYgPHHrF1\nKxvVtgYRuyftABvwWGSrLx5PXb+ccXtnT8k6b5fGRt7wiYvrS7r3rsIjCkZ5\nkFUg5lE78Hu+09taourKEfdYTCOcJxF41RSSvD4AqnK49uTL4CX0upr1F5//\ncKtzEkjUZkQKFdyEhVXPFiKJ4AVkCVj+QLtf/X3230OfYAg1D8GxJVWOEc9S\nCQ7fHB1Nw/1XbKNPCbQuWJNkMsFjTlGynvWRmGKRKjxHow5i+RDkBfJU5IYz\ntI9le3bEk4slypwi2hK/ShytDj5RtD4TeESRSF6hDht0UCBbSrgYgf2gG4Sf\nwUTQFTaiFI1/t2xtLq4ywmIVL/2WIZuKDeqLPKyAVEyE9upWp9OtF50mrpGr\nCL9y\r\n=8aes\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICUttj8Mm6E3BWZdTaxUgGIOYAIsIBB1nUuE8tKAlrV1AiBQE/OXELVxmxSY6qLvklnbb6ceVRoRIglw8VfIIRtgbQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.59-alpha.6-pcount_1557299613601_0.9399147612154999"},"_hasShrinkwrap":false},"0.12.59-beta.1-ga":{"name":"teambition-sdk","version":"0.12.59-beta.1-ga","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.59-beta.1-ga","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-apbL1Z3CT/eTLCZIN9qM8wyrdGg1ItqJhYGVuqTdkBCGhU0UczHRBvwnWuUazHRM6DFb/vWMy/+A3wkzhW5I5g==","shasum":"a5fdf5b3885fbaac548ea60d330629464032b163","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.59-beta.1-ga.tgz","fileCount":434,"unpackedSize":915580,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0oMRCRA9TVsSAnZWagAAS8gQAIkXxniFwNtTCWd5iVEt\npUbXULJaym+4zkKGgVWMOt0roGgX3TjSG/qkbcbIhGgX++M0UZamUAEGZVrd\nB+u2KDVlGPw64/clXhPLUXuM7pw6okQFtonKDtZt8wSORgdU0Y1axdmFWx+Y\nR829pUiRt0sfm12NoDmsibwbEjLYT/QQMlK2aLwHn2tHryCVVSbPEXvGyBVX\nWzMMKVYfdzH2KW/BSXQ1Hj6LT3WOiB36Kc4KKiSr+eXUu9dUkQllZaL4Rv0e\nXilZXMEHrT7BTPKzU49Ky6+GDKlX8tIobF0uu7ign+TGAszoYgAtbSDBrDDq\ntbJnEIi1QEaomfByt9izHelx4xJyCRu1QfCHnJufIv0BB1ErjIe5dgIgLG7B\nQ/RtDBjhGa6ib2Kw6o6AWtb4DQQyzHWPVoeje+YCFulovU/GAIt/WRYGVxiL\nU+n232LfFzkLg5xFcF798/4ziXXo0rA6R0PC9WtnBu5Cc6dGAzoyI1MtG284\nbrNyGQGBmMVO3Vt9mV5DOkZlYDIb4ZcV3eA2lDld4BTtfdmZFBw2QuncmK6c\nktgRn+TlI0gkqpNkJpd6uUnXjLO0sE0fdd1qQkJxTqk4DZTHSbfn/OhkdvtV\nFUiiqTlkHwOzDfT9p8U68rDHz5cnmmjxc4AfBPOuWAQL3s25gH2u2xJZEXRs\n8MUK\r\n=BsHc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD4WeJwut1Hmky8Fe6CqhSyt01hvbchqh53iCfVxAZgSQIhAODKYz3sAr8ve1RdJRpntz2q23xIKabKOBlp5/7Wc8A1"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.59-beta.1-ga_1557299985296_0.7703224528205053"},"_hasShrinkwrap":false},"0.12.59-beta.2-ga":{"name":"teambition-sdk","version":"0.12.59-beta.2-ga","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.59-beta.2-ga","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-tlYsBZ4KA7ESxP44qBLl8XmmLMQmnNpB1gBaHKF1fSXiEV+Mna1h0/BJMaTkF1opgxpTX6f93uGSSiMRXLeNTQ==","shasum":"81721a2ebc823c8aeacd5633bced9ea9aa8b8bb6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.59-beta.2-ga.tgz","fileCount":434,"unpackedSize":915334,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0oVqCRA9TVsSAnZWagAAfh0QAJAZZJeeb+8+d+ru270d\ntRCH6+tNBJJlX6mSzahlcUScJ5ojh+b883TOVpbMWS4YZ5Azq0k2+1CTciwi\nfW9SGjHdyR49LUKujxgTa306CqXSLd4/3KhwKX7htWg+wEryHzjFwUQtaQCr\nKe9biJ6IPprM0YhPe28E2DTcWCgPjMTaZWjoejLnJqD3tgxs5De3CpaCHQDe\ntYFvuJgUxaIP9ObEBu2/MxM+pwY3EtEDQon63GVnk9g2N5KRs7pSp+ZSIar2\noNXaW6jYc7KGZAjJsPDMep/7Qwgl9xYEO1sbCK7D1PRAg23Fj/Co3l9AiWHy\nRsHEASKelwgC89NhWOyI7+ZCk6kmDA6KGurvQd19PKhjI2n0D/Fv/xRv7KM5\nDzaUPb0jYRAa7r8Z5ctVOpTXLx9Q6oENb58lf24Ny1+E6dwXSDzkoe/BGf+M\nMqIp0YV6wy7Sr3wRbCzzKg/f7sJwu/0CTSSYxbr2KQ4Hj5+G0LIUBXKMkxw+\nl2OjPj+faJghU82NMIgLj4E6EUFJ5TfWjshz7B5hjRA4FoZ+wOpjRZhqiQSj\n3mmaphUyar5dGkn3PXClREjEsKr1BCFTFp/0l8WH8hyKAHZldPXHkrcisb6R\nSdRWEbyOo4Jdw22bAWozZJxLO0Waou+Bbdgpze9FyoizWXlGSClVgYDOXhqg\nDik+\r\n=WSAZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBoVWZAbT3IZitetZBYGuqNMbqDe3KS9WvgDKRbccNxNAiEArp9xGSfyIso8FCFI4fI5FCNhwN80iT9ARbKRO/KDZ3Y="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.59-beta.2-ga_1557300585537_0.2348573600531898"},"_hasShrinkwrap":false},"0.12.59-alpha.7-cfvalue":{"name":"teambition-sdk","version":"0.12.59-alpha.7-cfvalue","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.59-alpha.7-cfvalue","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-D/1iVXl8Qg9RxJ2oOFbQkFYHdyE0B+SQ3RYUircponLq6fpq8NsJHSv7C1xk2bS8pMy30evY9BaRlC7HoxSQnQ==","shasum":"be4d3ab241755dca1b581e73a11847c727f24c71","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.59-alpha.7-cfvalue.tgz","fileCount":434,"unpackedSize":914145,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc1AWvCRA9TVsSAnZWagAA514P/1Qzh5TCsGAAnrdqSXB+\nGQdJkuzZJIb2gA/Cf20hTp0xn7Q68NDvLmPCV9F8Ybxt1DdYn7TiimPLQE3P\ngo82loNgibV6H3SVilJYJmhVCY37YviL8iBOfF9baA1uUVvl2yyjQc/PNxD1\nNxkLTHOs7h6sYaMu1ysXLfj/mfzr5OzXkhDs6KOnE3q2KJDmaq5x/r0SNxW4\n3h6Qur6Yl+TCAC5Egks7NlsC9/gQQSOxonCr5PgxHZU6dKKJVgFS+ZUda3yG\n+h65lGlNt2iOKM05Ky8ZoAgmQkA5i0g100DsDWNBDZiLXiRzFNttgRGvCR/R\nBsQYJVUl8ho2caZousIeh9CPR5iNKcGQWnA9j0K7AKKGJpUXmOoyauXhagt4\nu/6o5ZCE1Nfw5ooYbpBbpnRnk48YyCpEPHB8glwDQNmuBb6WRVW5EixXDNgP\n1jbYVHjNyWOZ8kvDf09BoAQ+w+U3eVzWyzj9DumQEZAiq+NKS85eleKmBl89\nkiv+pGiXZRdiGiC6ts3BshYlWcm5JxxpCh2u5p4ashX8vaJYW+R+iLNNQPLN\n2WFDQBlGankTx75zoLsMFYqj1aMixpf9sc+mZ1UCVBU1abcxJmsfhzexO7Q1\n5n4MA3zws4+wETLfGCvTnVp1cclTaTdhRaK4FmDVsauQ8hvpEK1/ug+WNyx+\nlJnx\r\n=tiU3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC4bve7w1vpkUjei9o5fuDGWczNsw2ANGdl05v4Epnx0AIgK6L6p+OquVQfEhFozyiwE333bYsv8K2CGny8AxQ9jXc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.59-alpha.7-cfvalue_1557398958507_0.21155402213025987"},"_hasShrinkwrap":false},"0.12.59":{"name":"teambition-sdk","version":"0.12.59","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.59","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-FHwPTPJCI3lF7M6Ip5/MB+X3G0Rp7mz1IUKGQmn0l336Odk4dAZ0L6/3cGIA5lZBk1MhDRSY3jg+RY6Pz3iCTg==","shasum":"c8228ff090e442e2ab24b537796670d4aaa922e1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.59.tgz","fileCount":434,"unpackedSize":915324,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc22dcCRA9TVsSAnZWagAAw40P/iFlzGBOvVIO7OcEEwfI\ntzvAzwNTokmeKeZKg091rcC9gmmIriMN35bih7ROkTS55gWWWv4LhL9hC9UT\nldFZRK3NgFcUxK0nHS6njTbLcTMrXd0IxrEw1Na+thSyi0h49AMCv4G9bUc3\n+dSi4gS1kHx2KZWQCxwkN2os0VcQKZoT3Jngw9MqeTRJ8kbOHwv7X+7xU+KI\n5eC+sYF5J1FydBQ8P4RrCsJYczEXyzJjxz5zn+hKQyrqqfn6wznKC61+TL8W\nqvcl36s338dk7QGGMdtMZTYuVTArUmMYE9oPeYMVbIuFRg19kX+XnxTg768b\n/RS4e46/iai/50bmdAvy0F7vERrDoLk/o58gM6BLFl7dmc6nA+8zed6/+lP0\nwtdtf8G5gUzBEVo5aLhE25gZz4ehZMiRtNHhQ/tyNbyjoH6cO2LllhlNrZjH\n79BHbHzC8cq4mCGlfCjeFR907KVS1/f0v/96GhCrNI1JBWFqBB24ARtHwv0l\nXjuTGoz7oN15fK/lcYjnI/qetkjUD7IAtemvb5t99zmTdS2fZ7OINw2xw0pi\nLVyJGb1nwo9IA0EMgTrt3doSSSejjFoj09eLgHXjR0Z3VOE/c4iw+MnfJCFn\nldKJO0le9tfP5GTwiRg7wPgisp0IfHnVPuMOqD1OPhrH6TmBy2lfTD65n2T6\nENLI\r\n=nhXD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCm2QUiq64SO8YWPcQ69ZHGB+mrWzyX8f3bZ1Qefhh0SAIgdPoDqknHWgJKmF6/KXmd+oQ/VO3Sl3CPa0v1iQLHuoA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.59_1557882716007_0.5136092584700727"},"_hasShrinkwrap":false},"0.12.60-alpha.0-cfvalue":{"name":"teambition-sdk","version":"0.12.60-alpha.0-cfvalue","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.60-alpha.0-cfvalue","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-Xxun2uW0CTsIDSnImhy6G6vhmQ6GNhj5iUcfjElaCz5VKEWiTGsLVWZO4BBn2079HAeEtj2kFiqIXYmA5w0y/w==","shasum":"1fa45557f6f3f15d1dc03751f47a8b3f93d56bb8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.60-alpha.0-cfvalue.tgz","fileCount":434,"unpackedSize":915320,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc26+DCRA9TVsSAnZWagAAY9oP/3AT/+mU5EITHnjrEyXh\nOHT30dJ6CFFTvQwSMSZ7lkuR22YbdoTQKVRu1NADUSWINTdpQz42uGfsV05e\n8aV+Dn2oUW2tYS20J7V44NY1TPzt3VUuO891jkmZIRiE5TQHbqpnbj7VFrsA\nN0iqBuJ1GjsIfxZ2rUWb5RW8WSAoED48pFLiKETbRj32N0opr0PTkEAGb+T/\ny8dqthqUVZJ1MqWHC/N0B3RoI0Fg66v+G1vpYQ4RAFRkSW7vxNM0/LTQQWO5\nEdktUkB7tV1rHDNj/uMXJ3O2N2Y/WTQGX7pQCQMNRgeCJ/8HHFfOjisoM7WI\n+hBAzYENFnLccNIsUrpeimEIvYkkHFR0Xm3tV//XdD2ID8m81pkG4yUzyd/r\nHxb/XbSVs/1yPiyanaMlcadu1tvQmZFdIGefpsnwHtv4xzuCv/ceITUQLmKk\n963h2AANte/2L905UIvQMKMdxrWyubbdKm/AeGZ48ybF0mnhJCI/M2z4w+Lv\nn0QnBGoXsyFTIbcmii6yEsi7fvrz2L3+2Vagd7bqBOIjWMldBOApACn3mO/p\nflAs2AC3gg6QttZvgHpg6D/Ajz1QXhWJMqRRPWRj2LgYQKYfJb285t/OhhrL\nOT0Ubx1GIU0lLAqfB/hQa5W4jbAhvFPnqyPzprDZlpo5yp3b7kk5uFc2pYdZ\nypZn\r\n=9liP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDJ2j0a+YAyYnC2A7YgFUYwMdMDbm0PDiCAWf03xy1E6AiEAwDSRrkDYapqRW/lfkALrVtZVxjiYT2RLiDfwTrlGFnY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.60-alpha.0-cfvalue_1557901186632_0.39291590429760426"},"_hasShrinkwrap":false},"0.12.60-alpha.1-cfvalue":{"name":"teambition-sdk","version":"0.12.60-alpha.1-cfvalue","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.60-alpha.1-cfvalue","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-CFVFQKS3hcN2bth84q92NA4dmGGEINUxM/dtZE1F6yp62Z5dqMgH8pVWEER/KbKy1gj6juEa68jd6wGiofgcMQ==","shasum":"21f86aeeac357707e3c7836cefe6110d05f78c98","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.60-alpha.1-cfvalue.tgz","fileCount":434,"unpackedSize":915848,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc27sJCRA9TVsSAnZWagAA4IYP+wfihkfxnPYWpYg+jEkh\npevzGk6FVP2xtJUAUDlZ2Fj/dEzPTjJzFd24qUwIhPjcMkMG7KJvivz4NoF8\n/YizoGtB8D6LZL8ISSMLDXKy8Y28s7UB91upsloOthoI+PVKb4ClU70Q2Wl7\nIaWzYN0rHYqJy3ExvGmQdlH0bKbd8qFaFBbGHcBCY6IFJrP4q+qmVr0iSMMs\nP3VaQbra6kKN1U8dCeG1ni37ti2Ik/JUoEushi880UMjxHu1Ic5a6s5eg1VL\n8bkmJAHKo5vqQ5JjZW+W3RG1ToQynvhstpvx72W8QeOHUSw9kBEhdhBUil5x\n/QQC8z/u4gWOjOkVfx6o3f9aCOSk41CGxYtSYLGuCzy568HzSRtsFw4hTUSg\nkRV9ff5reqta6DjM+Cq72Lz2HHiMTCfeLMSypnCX2z7QgWGFrWTc+d8fg9V2\nuHtLyzCyrnRp7oHmY1MSDhTxulTdkToYiQdLn7F4N7Ocg4ePHwQ2pvzLTIPL\nt7fl9RgnvH36GPowwZMuCWhGyXigfCFrCq1G6yY+irLhfAh43YMeRdYHBRED\nLxMD0H1TVnOQIAuay4Orx9jK+As3vmUEQbw4kCzT4zZ5yCvm6SnHyU85tVhs\n1Cb9vrsyV17p6VpaPdt4cBxSgEYQ473LwtgBUzqve/M4qPNW8jmo/GijWd1N\nb/7+\r\n=5AP7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHJ8XGtlDH7OIfth9vT9QZpY6fzEgO1vJZR3gdng01UsAiEAuWSl8C5CH7tANN8Ncr2GD5Ka/n4p6kJnbxifU+rZB5o="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.60-alpha.1-cfvalue_1557904136334_0.9076175398754021"},"_hasShrinkwrap":false},"0.12.60-alpha.2-cfvalue":{"name":"teambition-sdk","version":"0.12.60-alpha.2-cfvalue","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.60-alpha.2-cfvalue","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-S0qTJleQTwWzYNNxy3N0LKoQ1Mb0hochTWTwV2ud/o/uiQGY5+9KS9TE1bZIbjJwWj+dB9+XMH8LrAjlaChQMw==","shasum":"f1f0a029e8c35a676d439f756174bae5372088fa","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.60-alpha.2-cfvalue.tgz","fileCount":434,"unpackedSize":915878,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc29OnCRA9TVsSAnZWagAA5W0P/jMzAHILakndZ982A0H6\nWVjd1j5OcQrGPwYu0hqx23L/VbXy1LTHWiJQ8zDO7fvBaoKAy7aay12qmnK3\nP/ueIsYfeDrL3sTODXd7CNQgYxk44KMT0lta2tP1c2NVYXl2iJyK9r6meiT2\nPCMQ3uhIAaea1pIzHLzeFKgUKtCOXdFE8hLfIXitZYueXSK4lQ2RA09XN61i\nXnbG+feYBArB/n8BQthTIDvvTNFG3NLgDzyKBU8CYgk5B7X8u7NsfgIlB3S1\nfCp6N+15GTGzbY1T9fXvDH0zw0YXoUVl7G00nNMoF95Nno1qAXGSIfR9zq6J\n1wH1/Fu0RefYClBcVQ2DmJPFHuAHkf0OsTsisxIwWUF8uSyB6Q+jod28TAip\nYr2HTlXI7EPLni+9dUNQyGeFgQXFM8qCRiY8ibTL0I+jAFm1wb8sqSMFvQD/\npO/uoIs6D6B16NvOgbn5XjBUkRKr5VQzV+nh18TqmD8+LcC0l/rWzCiWVhu0\nCcWz+SgsobCsEUgzmsIlnmvAOpGFpzZLA2RiI9TeoLQhqipIBz6lnx/KMes/\n8ByHcshOEtI0OBsl4g8TMq8dbJJ5fYHgMOrL8UUmbDScr7UCDswou+UUv8vE\npnwJVx9WZEEtXW093P8Lm3rsPChK/qKqNnodZlsf89yQIKlF6e0ptmDB/wEt\n3yor\r\n=AiqF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCghmzzStwCrPHb12HNF9kYaHDHqOx5s1irOhbjZiKXCQIgVUXiCwCTFAz3UNCY0TrANlN6jxr1p4m73RDsPecbiXg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.60-alpha.2-cfvalue_1557910438480_0.5410178831079682"},"_hasShrinkwrap":false},"0.12.60-alpha.3-tapestry":{"name":"teambition-sdk","version":"0.12.60-alpha.3-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.60-alpha.3-tapestry","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-3t7WbodfHeTtxqa4mlqzNRWuzRqq6XRvfprr8ldvJOLJpxHmY2iNMW0gtJmaRpemD7wN+4DeqfXIprGkkGzQYA==","shasum":"316d772b87a4120c6ded82a401965154027e6cf2","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.60-alpha.3-tapestry.tgz","fileCount":434,"unpackedSize":916341,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc3SOACRA9TVsSAnZWagAABakP+wWO5eaDBQ/rPaeJbf0g\nNKxGmKcs2xHOTC7Gxo0prx1PwjPZlGIRpaPjG6QbVGFYpU/ynluqGB7zVlOg\nnSRrSiBYkAcklsfh5L8RryFwoDFXUpwgnmJdHPyMQdzAGZmTHFmQmJin5Hvn\n4lwlZ80KFvgg/1+/iy4ObdKQgq4ZgnB8QZV77GjQbmEA0L0xgT/cuCSzKP+q\nR6GsKYeZb7FfK+6+5wY8pkECfqGCmvABCDK9sIZDfu1rw3bzEcqXP0yfsbqB\nXCaChlEhKjjJf/q9AWsPSz3cdFAk/0R6o1CQcpqx5RNTZUKgWiVy0jWyTnVR\npZAqByuxMB2pijqZYUc9oWPYISTQLhan/yV6NsVsBeaI2kdsNDh8Pj38iSp+\n2T+rHuUgoxAjaQq/VRtGczOPnZSvO6BTyapp3DH00EJjjUHdH4p+RVp2j75r\nBTcWQ9HVPMMkWBh2d5ZMEf+rAAVueP62tdVR+Zy0oxaegp6b756DamKbdBKb\nNyLwbGvrL3UOetUIIG3h5MZOJrakV+j7GHG145aas/N0cFSbBs9eCuKJmHTr\nk/+YOCvRhg97WU4iRjmzUneYEJ2MzGFXpRdsM45AB3NjznKtwLy/mMoAEq5E\nsE/XffYRpDYGrXGxvShJ8wxjGhAwcORB0Gr/0h7U84mpaTuDMxaeYHlVCIyD\nJ7mn\r\n=dWw4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHf14yoDibsOV0eqbhKgcfN3zPeuLBuIiOIZ5vq6WBL8AiEAo8HbE+z03nmdHh2l6qe21YBAA0yVhXFuCiAI8hTAWO0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.60-alpha.3-tapestry_1557996415538_0.403890543232877"},"_hasShrinkwrap":false},"0.12.60-alpha.4-httperr":{"name":"teambition-sdk","version":"0.12.60-alpha.4-httperr","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.60-alpha.4-httperr","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-Y5dOVNtHbtufnKwom2qlifHsOJUALUgiFhxW3etcjFGMTCOHUpEMNjQSKpU0497wLtmhDL4ULk/PTMM6GM3HbQ==","shasum":"05154a61a0daa4bf9e2d41fc51d180be74be7e64","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.60-alpha.4-httperr.tgz","fileCount":434,"unpackedSize":916057,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc4gOvCRA9TVsSAnZWagAAQiMP/Avm8Xj/EPhF+T7jh36E\n4bKnTQ3iWErZphl4apY+qFAGdHEGHdIJm7ryshO06/AT4nJEqn4FOAHA/A/J\n0QEdkzprLV9kzIFb0pHLMJ4/MLl4IQA18QvYbqtnG9w+k53FnIbvBD+IBs/b\n6B2n7MmtihjAOk8qwgs8UMKPwt/nHhtHeFpOKxqd9ZgwRR2RPvHlpEThJ/Sq\nEL0BP/3y1I+2Bnuj/MR/yqG4rohryBVxXOIMuAnlJXevRAZL90mwtu4rLz6U\no/vPhz9oJw1XRyIOB3Iiynx3qX5r2V38A1EJU29XOjfVsTB89ecGfg+AisNx\ndvjpgM12sRMdTwwp4GsbI2LK3teVOEMe8cwFisg8DiA5pfjavYf33GnYf5fA\nVHY/rWlfmB3ZS3SWn42KUnpx9lHD9IuHtN2a9qA/1lXIASCfCtSqPLKd/Xy5\nOaXWWmOMh9F3GJIirf+kcDYmvejmE5vexGXhMDwZDYSKqUEPFIC9uWrQrZxS\nYeHT8GYmPvSYeX7EJ3LHjFiIbOsEPoLcb1vIQk5M4Dx3qIIwIgvy7SaR7CUP\nJbeHfuXgPK5DkHs3bXLYeJb+1DTI3sAELlPgMslIGnTJQVoiGNy2PfiRPY9x\nHnnWk41AJk3QY5iz8/VvI3dxP01XcoVuvIqndQZRckujDjQIFl49apBc3JBS\n6rAr\r\n=dO5N\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDqAY52I+UbLjkm8wlFbh6u+mtb/UZWTJRe4biCoWHtEQIgF5nEKELoo2foC2HLWBfwIP25YtagfmcGd9oVyWCskCk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.60-alpha.4-httperr_1558315950738_0.36530261618000703"},"_hasShrinkwrap":false},"0.12.60-alpha.5-httperr":{"name":"teambition-sdk","version":"0.12.60-alpha.5-httperr","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.60-alpha.5-httperr","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-MBj6zIKL246E4FD2kKima8D6nO/z5BFfXn64y+q3U+ewqCE7xpchddKnpGhEINgf0UR19O3FN+BrLwAymCVnCQ==","shasum":"65d3c884b8f67fba6d5139ca0295157fd1a721a5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.60-alpha.5-httperr.tgz","fileCount":434,"unpackedSize":916057,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc4gZVCRA9TVsSAnZWagAASU8P+wSSVUJFMDbvwK0WWhMo\n9N18KDeUezj9+UtO/oxbovV19iqIU8Suao2usgzLNBZ2+SPXNNhsTiAmQ8PA\nTnui+MuXDLXC7752KunWVB0/2WxFbv//C1ysLkfER/+I3x4bPUAd9P1hfxpx\nAErmhjMq4Gg2iMvbUBKbd4fbGbVp/Gs1CJkZ8MfGvT6Bpk5vXuSXEbWxXdVv\nGFuLB1+3LIMrRR0x8iQbj2jwI/JpT2Y0JOzLo2Dom0FQeuwjqfYO/bdL+Or7\n4LDyaVNpigd5iIAar87cNu7h+w0q8EY1C+iH+NS3OCOTX9fZgJ2br+T2GZX7\nnVlSqeVOlF9FlS6kab2EPjRwHYPqEXKLMRSLpRIT6VDCXBw9e1bk2yv98+gf\nBnaciq6GFbLPuASQjZ9V+vhzl7PDC0jrwYkngAcjRvlHnnsbojWQ1m6GUxwE\nAHUGS1m09zCCqgNjkSfUOudkG6jrLJ7nJxS4OIePljBJOxotKR8zBzsPHSol\nEVcrlZq20x/WUL9RoxNmr/P+Nt7dOCUF5AiFYcIrHKRcpZCDAb7eP5ezGOB8\nNLi9FemIdIYFCjsqgqFFQMdLhnYm+p77g470YIDe7YOCIWd0ACX4b5KZyzRv\n4cizKm92bR0EOkJ3o0a27tEnY7jC4iq+LX0wpblC4fTtRgQZqkhgbR+LNaac\nKe1h\r\n=2Nlw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCEHvjwLF8vQSgCUTsCzI4hPRagOzDcJbGrD2vGwsssZgIgY07kaVv7N4HKjidO74Nt/utJ6xnDnAcZQstIFQZf3wI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.60-alpha.5-httperr_1558316628805_0.22261869965355285"},"_hasShrinkwrap":false},"0.12.60-beta.0-ga":{"name":"teambition-sdk","version":"0.12.60-beta.0-ga","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.60-beta.0-ga","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-e57Y39ETjoC8GXfZB8fkcI2f0EOlixR1hresPvhT17CkTlAIZVaPOMYRJXHMqCliNVsnKfnGMh7iG5R9hmPGxA==","shasum":"8f7aac34fd31470bb05b418b7151b2dfd0e4831b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.60-beta.0-ga.tgz","fileCount":434,"unpackedSize":915886,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc5PuLCRA9TVsSAnZWagAAsZMQAI9nxBkghjo5TiGlrBnP\nENONoiqWrIdKRrI2i6uCFkjXTNl/+doQDZ5Ors+MjIPi9LvzSH/Q3F5Seu8g\nDHYiwwMIUkkyERK4iT5Xpz6szJZZTmLWEL4Dor8A1ONLWRrMwBQTu3s86sm5\nkmGXjSTcf30z8R9slGy8d5vJIfNDEenq0eVN19vDFhiK4dT3ARWI4Slut8/r\nm+hiOrCelJr7hZj3kf6jyT/PJD2vQkMfWEBRSm19lF9XBJ9Hqukh+z6eQfq3\norLxzPF4uVScuYRi9cN5RlUYJQ34wmA+ZCuQySEF1/9FqLHCW+NCv/x4zX+8\ndTaFFgo4z8dxnG9biaTc2BXyXXDd3mVpU7mNpmC9vz1deC2oq4QoJf7zvv02\nBMlCp9JRivrZtIpkOLTRgVVd9+JdKlotweFzzHoOKszrg8P+lxIakAum03Ik\n4uPYwlR8wQxrIH3aG6KZn7Ak1ALvVNlOtlxfXwSKMayCUpM6vqYna0zx2kF0\nlf3coYKyXU2Cvb/hlcuseP0k1s443jB5eSOLVp8QdBbjcsM00frJRoQki7bt\nHEigy+0hrkMY8w+dv+sFQMAHA0rsC+AuQZG0n5lhMRQE9n2LJ+Hpl7f4WQwn\ndVgwuahAaemhsZYupl7gJuMH+WoDkl48QrvWxJmfGaZMjJkotABFoqYalPv/\n2Xww\r\n=6C1k\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDOvt7ro65/YuUSsoIOMVJUassBiJn65F7KxfYTJSgjLgIhAMwgiWfSTUkWn3D8ORlHQKtHNyrgFNy6GEgXu/iAiZxO"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.60-beta.0-ga_1558510474418_0.9932923841751655"},"_hasShrinkwrap":false},"0.12.60":{"name":"teambition-sdk","version":"0.12.60","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.60","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-UsRnafv2q7F6W0g/+T9kwsPJC2rGn6qSX3zDPAwF6knXUV87dJGtWl6I5Ain4eGxnhVULZ4Yy+A0SFBX7VwCvw==","shasum":"331ed466d0f40063794d784c88e3ddb581cbc44f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.60.tgz","fileCount":434,"unpackedSize":916041,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc5gmiCRA9TVsSAnZWagAAN+AP/3N3VIziZjno0RXSYqaa\n2Tjpuikjgxtc4i5b0W+kZXjxhguIERZNgqplcviyfi3WPlQHja1F1Te+BjKu\n5aMtcXv55GkGgy9TtkAIHAUNV2az11M1QtWY0p5fvarwfLuXQ+k1sCeWES9R\nqZm/tVloCRsTHMZS5J77F/Y+MrW47034Eax+qOKnoIW/T3r3G3IQwhcgSzwt\n/31PVFXsPPSbsYD9Ahy/UaqLBbOncm/ScpYnBu54I7iDD2meb8ebH2IMMKMr\nG6VX12U7IdfoJlmkXGTwZOtkgg0mDNQw8QW8y4ipafKYghVUJNCXw48xRAJP\nBy72zuuW3KzQzg2K/LT/QcjEDCNDoaB7ivTHMfAuCbmjLnaSkIbvPXH+hkX5\npD4yiWMBwFIAV7usQkVprPhj5W5mCKL7FVCu8dGJuo7Rlqg+ttnbSFDs+q78\nD1pMSIbFK175nQ6E71AqZQQMRqm3SSvweW2xDUlFU4a8n7aB88zsvLV2vMrO\nd6MXnI8aIuLkO1439JQVfnNzRXchI8Aonm3lgvgVUgVKn8qeherD1DwWK4VI\npUnRXYCVGeSnC/Bt67bGEXzg5b8dMFzEaHDm6XxB5VXkCJAOCSutwb2O8lGd\niTnF9dlCk7Bxk1BZENOJNFu2JoWFmvodZtmAW3Mj9Yw8/AUIFtBzRg8tUE1p\nP6Lv\r\n=SsA3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEJClPQmINzHKvmvp3fNOJmHWKLBn7EcYxSJmsGhx6P1AiBm/HiRL830Sz+IxrA5LmNC934H7ZvYY/rtMVL5lFHqgA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.60_1558579617408_0.3742451924375487"},"_hasShrinkwrap":false},"0.12.61-beta.0-ga":{"name":"teambition-sdk","version":"0.12.61-beta.0-ga","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.61-beta.0-ga","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ELWtZxXup/hZrw0Bi+ZEgdZsl+bapqxONnOjTwn5w+BmLaMr0S4th4CBHpgA//0SvC01EPAU09xGuUt2IRzy8Q==","shasum":"d22c6e888fedce728139580061a913d35bf90939","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.61-beta.0-ga.tgz","fileCount":434,"unpackedSize":916603,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc5hAMCRA9TVsSAnZWagAAqb0P+wWx9q/x1cUpH3+aLGCp\n44kwlICAAeBWlYldK3+uqz7F04a2+98HQlVHk1pyPtRu/4ZhC/IrX6cV5OmU\nAoS1wv8odZgZZJ+5TTlgh3jO/4yAIm5srH00wPHdF6lOFx2pfcvyrIkFTFgp\nGf7RjFtaVVq4n7qaeKcOguWw87DffMLhga50Vx1nI7mMjriJ7LZbkrxNi9CJ\nG5ErpDNMsPqonqeOmVdBqWpDT4AGy3ZeHUw2YYmdbPFKU61rBqr2qjeYMzYl\ndT0iZ53JdqXOIIAIGvE5mm2jw2rfcsl3O0OBh07wl0sVkafBQBa4ESOxveU4\nfk1/QVFcC4dgfqg+M/y54qopRq6EwwhCF3sHBiIDF1RP3nppc4t7Fcl/b81x\n5d0Mm0A6/4R/njPiIkqyCzQm5SwKmyiPmGiLvPrNN0dx7djQMeFSXe4CIXC8\njy+MzolWR8N/XnJShVjPwSsmFRGispmJqVejhUodtIPfKaWkg+h0LP1+q66j\nC532xYFvjLE9B3OV2yjXOnaUCA8CXjknucLnaVg+15Cl7W9Sx46CYVy20kBT\n0mTuqw/H8xgxcK3Oe7Dufw+RH7I7E3eaPht1bdxWjsoAcpeCB8mhrkcqwZxw\nZ4BK2XT7pvcUeKJz1tTB3t9QHiZNy6EoayhJk/uyZ88i+wI+y9bwgxEeisuk\ni6TG\r\n=9mRM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAfkDmSA5SyGOECiUI8+t0tbD4V8Hqu9UHeJuC25Y79PAiA6QPuD6APOIfD2N0U8HkmEfgNroxpzMlg9jIhrbG/rCQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.61-beta.0-ga_1558581260069_0.4973935451219187"},"_hasShrinkwrap":false},"0.12.62-alpha.0-tapestry":{"name":"teambition-sdk","version":"0.12.62-alpha.0-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.0-tapestry","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-HBucd+xtCS3ijKvTneIjxmRffKCJYSYfig42GJBwJ+ldSI0jYC2F+7aJwIw2V8Mf233IbgDn7/DHJBK8Gz/b9A==","shasum":"f93ef2b7e9f91ba2fc65af3a8ad6c980ecc9847a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.0-tapestry.tgz","fileCount":434,"unpackedSize":913565,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc54HaCRA9TVsSAnZWagAAO2gP/238QMEOpqTJTlyY7cau\nfq6zvzVhUBR8HQYGbfsbCjYvYavdRDl5L2ctGsCj3Rpf3RHAQxt5N+NFMxRs\nVWuplDZyXGtIsUhFs4zZhEqciE7XDT7Qrld4SgUZdNXgvQXyvDlph1m7l1yw\n07SM3gSXeheNNj/a2KoC5q6wXkjYlmXQHwd7XlSFPUPioPecjFTK+pmeDvy4\n2QFmpEjI2QD4JREtdD6K5UtJveq06Kbb9Rs6iWUrBuX3cI2SndYyJzLXiNth\nCcLP7F1qM5f9QhcKVFpUwRRdRTomrd+T7rvCc+yRvDBFTlymVBbga5QrBfo/\nWR0Lqbpi06+cKUiLgs1/jKCG+NsWs8oMppos+BkUd091RFOFnzmUpZGH6Zl8\nYig7JCpdnDOJRFxrhaJCNJeCfgRKwNkfMoV78YqlnncwJegIZLhszMNMSRb6\nMOouXBqx/tbQH2evqsCqT50tfN0mlBgXmTny05TM2X/xzdVhdkYVVgt8lFLY\nuMjuxPJrWwFx73lfmrAOEnJ/zw1/s/bLFLnug3w5k2G2QHS1rjAFh0XwjTOr\n/4QSrBmvUCMYOctFLFKRB4pkhkCtiXE+Mcy9jAT/c/M6q4ui9+/tL3AjUSUR\no2F2LAdam2xBtwyos0GnOji6WN5J0dpfX/Ix5fw+sk483HpvEXQjKjIuvUM1\nSzm1\r\n=/hoM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDioaeWU2D7CxJ9im7NvZIAzqAy67GcqzjtZsw1uCtHvAiA6J+MOryvzMAZcRZs3BnJk4w/kqQIwWxQ9pZzppAo83w=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.0-tapestry_1558675929696_0.7909038639073824"},"_hasShrinkwrap":false},"0.12.62-alpha.1-tapestry":{"name":"teambition-sdk","version":"0.12.62-alpha.1-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.1-tapestry","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-JFq2/VENXXl2oMtzx5t9bol9NTEoWeJfemDlYgHXAocBzgiCyA3y7ShrGy6O0Vf0T7cdsVitMQO3rNAc0No/kQ==","shasum":"333af062db3792f2c4c3713e4964c8850999d167","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.1-tapestry.tgz","fileCount":434,"unpackedSize":914282,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc54O4CRA9TVsSAnZWagAAdpkQAJQw1UH3IONyDxfUTmDt\ncA/BLxkc2BVwUh05A4G4hM3eU5OzTWQKWcbaQ1ATlU8VxuJVme1paORbV82a\nzsrac+c4lz5GBSURP8ttDeAcJnFmhEgaWlA9FQnGt/vCnbxb3XMrbupLWptg\ngRZ6Ks4wJK8oerjxxwhv93542S9KipITiyxj/r/govHKM+RXenp0iW5uPpqK\neWR5UXj4CL22FH3UnAP/OxZrv2pifMONGr0jPJrdU9BZ2tPr0ISRUxxRDnfX\naAL1C91VX9oFm3YYnvkXJzDi52QZEnmo0chfuwH8idu2kioSt+R0qmESzhS9\nix3gLPocFUmtXPy5EOH2DAwBvuZWls0M+Wvz3880zyYRxMgdivb8vNlN2Zwz\nufCGnZHDz+6JcVWaGgLoEqUpY6u+t8RgPDvYXjubwzvUo5cnfj/GIEN1RjwT\nDOqcv0119mfOifd9MnAidRhe31qajyc2BbFc7VLnCZHEnM8vZAMeCpw9ZO40\n4XL2Xe4GLojw582vRUG5jxmSCBiTDTXGBQcVeOntvwz+FlRLkLUyflFCjpby\n4xpwR5mq9AXjmN/lsh+/4PKUun9oQPCjpr2W6x6c3DbVLoAiXmLHnhX+wjWx\nI4WefKxtoOe+GCcGjfmFpG41NW3srTgkLNsIihuZ33kqgdpII6vjJkQVceNo\nuOD8\r\n=DE85\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8sFQGdGMWmgecbek8tb9FYtCrEVC7DoF20x4zLQLRsQIgU73oiiwjNZ2tUhkdMr0IZ+HLcFWsksOtJSqIgNz7mYM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.1-tapestry_1558676408068_0.5471389092698824"},"_hasShrinkwrap":false},"0.12.62-alpha.2-tapestry":{"name":"teambition-sdk","version":"0.12.62-alpha.2-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.2-tapestry","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ECH2KxYJ5Kar3Y2xOc/+PbuLdcWBxQZ0sBMJw1E1BZVC0zje04528vYXEiYevUEdDZipiunG9nTlFDMdz0YddQ==","shasum":"2b67aa6c6b41dc186fb5e4c7a4206b9b16735698","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.2-tapestry.tgz","fileCount":434,"unpackedSize":914834,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc54qACRA9TVsSAnZWagAA4kIP/1+pmoBXSHb69eiuhvxt\njOrkNeX0q+VgKTYk5drkk9/Ou5JcDgCW/dGmo8Q6qQzVFueDE71aIOIJYfS8\nPCFrpn6t3gLOj87idyfCi43b+J09y3NdeLz5OFuJhjL/do8YXJHhxhXsXV4/\n3sLG1+lN0KKOs2u4PltG30a63n1pS1Q367r5Z+JJpdbfgMIG8JV9vPJI3kOJ\ndEmVaAkTGiW1Ugk8XZEYY1p37RUf7K/CGXpCV7Ya+KOknkOiSnEzh3+BNPBb\nL96g4Gq0r+d8uHUmLYCoNFzoo6hxn04Ex65oBeWjMu7fj1NgrLgKypC8hs0I\nLdJfrghrQ7QEfdqVjMcQ/blLN1g2Em38t4dfsk1Obx1vYzu+WI+3ZP9jo5D5\nePhATHWStHmYhejt5QlzGpjBBknsKId4EBU7cG9uzcLT4fG/o52ZWG6b/fYJ\nNBZ4iiOGe0MAcGxbiK7VIuZuzE075YoCPQG4d1ZDLTq+4cfBebloI9MDi/KB\noDUXLptzlHJzOW+sXtVDNws6XE0uoIWbj/wjzYhm3HHpFoiMIrJy0NTFMCZz\nYEIIZkmEHevYbIvlZLMABhx4Zso+o3Gwr3nZAWbTBlBLoOSZSUgfnzWe7cGn\nyiLeh9P22lbp2FA0yq07HmbAd7b7RtjVJ3cxLPkgoW7xWPM4fBX4E6ZsJauQ\nKfD5\r\n=J3jC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEvXXatvfGX1jhoaWHsdZzcsOOIQL6iPqbGQLsrVBfPIAiEAu8hb5adLIcHNm0QhWdaE1h9I9V2SiMbPlId6kuxRLyQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.2-tapestry_1558678143492_0.7068446235800787"},"_hasShrinkwrap":false},"0.12.62-alpha.3-scenariofieldconfigspagesize":{"name":"teambition-sdk","version":"0.12.62-alpha.3-scenariofieldconfigspagesize","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.3-scenariofieldconfigspagesize","_npmVersion":"6.4.1","_nodeVersion":"8.15.1","_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"dist":{"integrity":"sha512-6ieBNUT+VAfs2va3FEi4Ke0Pae7JsKr5Xic97e7oBo2MaxiuK3WTMJR7bO4qOdZAXTSW4L9/4M+DG5Yz7SAPxw==","shasum":"3d335aecd1f8896bad0551411c45a61bdc789bd7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.3-scenariofieldconfigspagesize.tgz","fileCount":434,"unpackedSize":916548,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7hrFCRA9TVsSAnZWagAATCsP/2xy3n4sVjeaQy6CHChy\naoG1pRG2dGJUGmtVwSLKoaY3UOWW+i4GVVkc73IAmpa8DOwcJuyTbXnBcjDF\n+0uCNAlTCvaudgpknzcNK09CUQfVTpZyJ8HFVx35gzpSL4pgYX/KTha78D8c\neei88sPAxIfuoiK/KtKL8GRF8Pc2+9TN/drtJjDbgK+i/AOHT0kC66I5jlLi\nrsNvSeXtu275d+GGLc02Ap9PbGLRXql4mJrP9YfO/Y2KfP0tKj3pzT4aUBLZ\nIkgiXxeymz3Ov+/iQumnWKg1TS8N3Z3gXTW1PICJw8Zh5ah22+v1lh3nLVp+\nmUtxWRurO70GCBvffp9x4El29bxVo5Xy7XnpN+AAlL3QgvUoqeBV71RtygG2\nGZHliZdmIyr3idBDdH15nvoBFm6p0EaDuLQ3pARV7D+Tet3TFwAQKI/uD90l\ngM5877yNuzs0VtFe+EiuLuY4VPENRIWuH0NpnR7S53d754FuPID5gpwOZitL\nPLUP/cgmttu46QCXsqePeJBFWjI+K6xfVm7wOhmLX9guitFPUjsIKSw+2251\nRP0OsZ4Ya7jmw0iRcwkHuTfBwfPK+TMTu8APwwtXLIegdN1LVbIgT83Jf5L2\nOkO7TjivsvhsUl621P1kos1yAhRN37ufkQhfGTzr4FlY0Vy1wEn1K1GoZ4uV\nTHyo\r\n=HLSh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD/VrZeHv/Tynv6R5sw53PQoCw8JgHsbIlYF3vUPa9z3gIhANfiCiAIm6/g9xvvTulQmxEVTzhAZ5wCuIkrqlPAZjbf"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.3-scenariofieldconfigspagesize_1559108292921_0.9106037218757936"},"_hasShrinkwrap":false},"0.12.62-alpha.4-scenariofieldconfigspagesize":{"name":"teambition-sdk","version":"0.12.62-alpha.4-scenariofieldconfigspagesize","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.4-scenariofieldconfigspagesize","_npmVersion":"6.4.1","_nodeVersion":"8.15.1","_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"dist":{"integrity":"sha512-icbL6AwiEPCDAZvE7ZAtWPFA5Tyg7uVlnwfGGj0O3VpCYrVYrApnZGs2n3E45GzCWHddGEmh92hXcodTrKrZ9Q==","shasum":"18ac74b1abccef34e1341fb702cbc51238d5a0ba","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.4-scenariofieldconfigspagesize.tgz","fileCount":434,"unpackedSize":916548,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7hxYCRA9TVsSAnZWagAA6O0P/3NL6IGYOuzxLLhAlPce\n122t4ofjUIWXwfLPAbYp8VUf9zYKS53U65Ll1RBMPzqaHz9BXZuDzL0EZR+n\n+TknN+2EN9MyIGRX3xKa8DYPx9y32wjOYuMtTpzyNx+HTWhQMazmBI0sSJIK\nHcj80NzayPEwfGKWcDw5I3CVq5IVjoVoS6gMAlH1a4d0/+csuXw6sYu9mk1u\nxYDOqk8hJh31mqIryo/YyB0kNY59pzA7Pccx5753A+6nrBy7wr1v698vSDyC\n6776u5WV3SpRC84yEI0PbX5svzitbm193+mJGvW+ACEjwqAn14NVlcd+WZ+t\nRCSWvhwjHML/hZ6F/VFJ8lXF2rt+zoyFH4hYfWqXbGJTvSBi4SrbztnO8c3t\nNioU07RmpI5BxCrU9bSIwIIK8mCiO1SbUvqintLAvAFhd8maYMMAeWMNdsSC\ndw+SKjLVoU2XnOcVCbkxkZTUjUWX/EZkIBSFqBsw3izHmpTbdxd1JvxUkbBV\n5AIlTHVcjMLttv08ch1XT16A1JpSeQBTrZqrh2mPGfcl6DlHVScX/oaNjz0D\njuDzwt8sL/XNnSKj8GeRwPxYA1vSHQYqGIFexm2IawsuFaiAb4go5iaEjO45\nSmSy9eZj7qfTtjf/G04NrRd8v+MZ/4K7LvtDtoslysautSWCH//dHNluh0Mp\nTjwD\r\n=zU1j\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA7Thhkrxrff+hiIP1JC9V+hc464XegUKG+VgV8aHBgtAiEAkHydDojX6RdghFmIU23PgdDQAAIZaC9jGEA22Uam3+c="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.4-scenariofieldconfigspagesize_1559108695706_0.18408571399719276"},"_hasShrinkwrap":false},"0.12.62-alpha.5-scenariofieldconfigspagesize":{"name":"teambition-sdk","version":"0.12.62-alpha.5-scenariofieldconfigspagesize","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.5-scenariofieldconfigspagesize","_npmVersion":"6.4.1","_nodeVersion":"8.15.1","_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"dist":{"integrity":"sha512-Kk16TOe4TipQQv7OZsr1Ke0udXoUrgFF5CXjpacFkRL1R1T1FRanN+Y2lotHondbEoSspb/DoDifUA69CE/76g==","shasum":"40d010ed5ef04b0e6587217857bbb89702b8eed6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.5-scenariofieldconfigspagesize.tgz","fileCount":434,"unpackedSize":917100,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7o44CRA9TVsSAnZWagAAugMP/2R+ojshUqQDyQW81liA\nw7+QioPrxGsSIGZwDFs1aCZ80BPanOD0bZdxkfnAmPwhRT47XeJvFolsM4DI\ng8h/V+8X5R2tPjjtLNgBfygq4+vWqGyDjTA24T05OLCsRJeyHfxc+haW5G7V\nm92olXotvZupfoDXFJbEiWwpHxepqTDF9SeOjJBAQsOGSse8kFGxuqBnjtLu\n7deQKdTK2xldgBiETUYIXJ9au18MtPvuvbgL5+zOYNk3U2kb5auGNWZc48rS\nlY6jXubR8RAzmQNNI6t6KsYhcghjtRy6qC4Zd9qZHS7pxL2SaAwTtMJBA+dP\n84qQyxO1EZpd2oO58isjARtA465Edaw6KIQAl7Mhl9I5a6V2Eo+wdCrixM0w\nv4UtW8PzWE5re2PthnExYMvRTXzFBDlxN5FI6OM8mLnUOIFq9n73OhVLcVKC\niozRb6kpGeK0UzEUH/KdrF7sTJkpOWjWbzUJYQDNxBMOiwLURrz1XUvFvgM1\n7YKCyM2Mr1JyUavrgKuwmLJ4C6+Raot0CNu+rWBcae2VrE14jZOxp43CVzgV\nl6cd3ilfDXxIniETlwnhs/2fnAuquKStrCIDMxNEO4sRagFCJPjPUet0UHqM\ntUQspSjtvD1IBjaFLOTl+eB7bP3BZCpHlL81NsnT6kyR15MoMCaN7J3vrMVr\nL7cv\r\n=z2bH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDz6uJQ/P2279LjP9buqJ3vNB0MlLOWZ5jGiqT+rPYRdwIgVyNdxVN/6cJpmGtpB3mu85EP/yvOj0uYvsqOcUc5w9c="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.5-scenariofieldconfigspagesize_1559137848052_0.03455297297368687"},"_hasShrinkwrap":false},"0.12.61":{"name":"teambition-sdk","version":"0.12.61","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.61","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-zSt5U5r2Qq/mtvnuAZstV1+5lqm/ogzajlgWYAVyzU1wptXD5gzzUr/7YwlQUFagShCpPmHwePi2NwGUrj83Vw==","shasum":"26c988fee0aa8870d068637404ddbad1333cbd07","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.61.tgz","fileCount":434,"unpackedSize":916593,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc72qCCRA9TVsSAnZWagAASxoQAJsz2feZeDs1z/CiQBU5\nivHDuL7qcMpoXaxtgViErEZ7y7aPAH7s1GX6hg7hx36pJ6vRPOx88OSDbXCL\n8o2h01RjwQW9cbjGRFh4arUsb3hCcOeZETt7PBin7lMsIaSHrEmIFPgfWQNb\nXjCbhZFOOL0BdSRefiVD+ylVoMWDdHEUxFdM7gs6ivb3WnKguMBeOFF22mOX\nObAUwjUP3MPLFgtiZgmh2yW2AGIo2Y/9ZbS0Uy8M14M9b8sUBdQgR/gemFBe\nIDA56LHoOWh3Aw8NUpc/A4rdgDJHC5ndv/MExmMp9eJpUtCm7LpePIBvsxlu\nJiM7vY6cTPyfkF5n6gbS2xZrMw9rbw4YNd/ZPm5rGuqiv5lv5/gRngwNfOxi\nWUiNpZSfX3SIGpHprnKO+uqU/QYz5dls8gN4dDrGfgKU/DgMw5udKRiqOpOR\nQcxGXCv6wZ8pDutGQzipYpLd9fhd/8Qyn/JPSK9gO1MmYtXyyoLISp0FuSUo\nwpWCI67Nv5TMJ9WLfxRvM+RD6x2SGWxsvZlDnB+zDggH8Ahb0co7w233NL4V\nZsSlfm4qEdgaXJSbuHxWOkln4yd68gXAc+Q3ozugixD6EfnqFBeqWLbwRdl5\nTzA+VF9aqO5kNh5XksOqmgTxm1dgHxlF32OL2/wqM+S0XRj3tCOFK5YTdUzg\nBzlK\r\n=dv1u\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICFkxAH7PpM151YKD4fk1P7bF+OzDEes7pKfRijYFC/wAiEAsgm/Je249OtK/shmKa6Fdsnq2KzAP1nnw8HVls275ms="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.61_1559194241814_0.20860785832566298"},"_hasShrinkwrap":false},"0.12.62-alpha.6-tboardrev":{"name":"teambition-sdk","version":"0.12.62-alpha.6-tboardrev","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.6-tboardrev","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-Tq7llYtWM/uN53K3RqGHnrLPXWqBCPwmQe7TJ5Tg4C86AVLxSsOgRfYfN67dM8I3GDKi3BMlFa+w7LnSLl7Yww==","shasum":"4acc37963f10019d7ad300f660835883791edc53","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.6-tboardrev.tgz","fileCount":434,"unpackedSize":917223,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9j3MCRA9TVsSAnZWagAAnJIP/iavLhPzSCwJFL5OXDWA\n6nT95MKFRGrgmUNlJFdl0BYCu+aa99nFfvyQqQ2f4PpGqASTg21P/u+7670d\njFKZ3Klcvt0/QNsnvy58BopA/cmMJ6yYNdgSlBY2jGbOL/RvqLTmGigiyrzX\n/PfClID0Kli0VApJj1BYixi+MRxE+6q+sC/tK1HadQVl7Yc14Lyf4bBk9Elr\n+WUy+n48xfV0bgkaAzLX51C43dASMon00CMyGOgzdzQi9pNP77l466J8JYUL\niss5b9KptzEfYvYHB4Xj4ZfC6Nx8OGpnJdJg3wSl7l6hVit/SAZteEWA1DVn\nTsnDFjemYe2U1hee+U4wMnTES1niweaDoD2SpUTOQqV1/XjCByduVwkGWuYR\nme/ExmFx/d/7/O36gPCL+AWFYBFWFiMjTEF9fsODM5Hu8BpJW/ydf3KONjpe\nr+s3OEqFTZnKPXjqEKJx4LfIMWr8mWpBHoNLaKh21B1RLO8GYQRBnrKBMg1u\n+tmaAVEVAEaA0Kth4IKHLXdMzY8yUxI+A9ebiF4Xz/o31yn0LqlT9KshbNKR\nXK0PAjl0DkjGezmU54/xObL0ZsNCI+DrVu98tIut4KYwe3xvI53sRIvyiamj\ndMfJriOu1mDZReWOgqHTJFgIVA1kHWJd1aAVg78a7dLGl0ZLrRgRXeI6ecu6\nGaUR\r\n=sH7G\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE7ZLoBhRaPs8QXh6NrPoM8OZVuVuPDk1A01Nz0MlH0yAiEApj1foxCdOypu17gFWsVSoGjOlY9crCvoUtuc5u5FzWY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.6-tboardrev_1559641547677_0.7219518814145682"},"_hasShrinkwrap":false},"0.12.62-alpha.7-tboardrev":{"name":"teambition-sdk","version":"0.12.62-alpha.7-tboardrev","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.7-tboardrev","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-VPm65EwyO01WzBIRaQyEVON4/Kv7LpspMbEkRXThGaYzMEJzcsHgTTa+ZVbFEaTEPxm6/kPYWmZOH/vn4fl5Jw==","shasum":"1aa5eaeb1283a26065571f2c63b9e993422598f7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.7-tboardrev.tgz","fileCount":434,"unpackedSize":917320,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9yZJCRA9TVsSAnZWagAA9jIP/3jKzVMcYwX2zFV5pvUb\nPo4kuYRbekhx+noPvmZG7dc5443aIJrWjbMm/qGj5pOaFGvefeC6SbDfLIIg\n9LB4ye9QVmCVjZyWVv0keY8yWZVP59HgEAQIWiAzj/41erzcNm6hBczctpww\nJ42igtyEgqlVz6n0k51VBQ169nXwnItl0Y6j44B95OS9u6RTH1pcfGgSO4uT\naTTgErgoYf01sGq5CNFZ/bnUYzeKa/S5AoeYEXhxFMFi9lauq/aFSEzKQK3N\n+8pjGXNQUXrhZf47a7xPKO9E+nf12xeTggag+LUQI1vLwN+ySCSs4Kvhx8+q\nV8Z5FuahWsBYqYVC11GK2jQtGAqjU1RpFNB6egS+6/rSW22ffh9eSo3G5fgn\ntN84J2aHnm6T4vYrpv/ZubGRktlELWGX6KGaN0fqMjewR4t+IT6Pnu5QZV+m\nX1nuofUnGiSubJGPtP9CfZJ+2vl/I05cjGn8Ez5CePx6oRmiDRYmFq4h8GnK\nE8ZLRWl6rxvPpKwNpjIEuuMVHYOaQetDBTnyOqAJXN4Y6v9XN2j5j/iSDf+T\nTu6Z7NGnA9X66fVr5pmxZFYRUvB2/aGlW4nY70+2mRticXShCz81716lMTJ4\nF1k0tpHTki4myj0rJ6zQU08244I0RAGHpGPSO+FoqBR91Si0hiVTY0WDaZ0w\njV1L\r\n=Isj7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGCvQlBsO8TsKhXb76SJYsKzFqXwxes/n2OlHMctfb1TAiAnzUnihtWSUPiZiCDwGpfS8Jomy/DZr9PKeCSbVYqWDQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.7-tboardrev_1559701065133_0.5243629690137885"},"_hasShrinkwrap":false},"0.12.62-alpha.8-tapestry":{"name":"teambition-sdk","version":"0.12.62-alpha.8-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.8-tapestry","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-JTK89LWVBvZoPxGRcbPESoiKzupr861SuWDCkUckZwG86vOZPxpX4CYx4xI+MI2UhmSHQ73TFbVhvw5sM9H0Tg==","shasum":"38c37fa015d1f5bccd9b2c7ca8c052061032d02c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.8-tapestry.tgz","fileCount":434,"unpackedSize":914834,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9yuhCRA9TVsSAnZWagAAr0QP/3C3vlCedlaprBWJQWCe\nYVhKs9ZaKPvgjzjnQhJzDF2X4yU8JhArtQMBrrtah/cAdqqqgCD0zrobEcac\nTryaTn3uM2L54lnF6aLQHI7Tckkjqywy9ZczrlYm9koPRc3ngZphzrvLvP+a\n5j6aEyCZVak0pcyCuSFVq26CuEf1R7hsEZL3uaSgWRQexnCOX0UH3iyJAOss\n1KOyoN8DOoWdnzxz96+2XH280n80X4Hzyfb6tT8vQ9WWsf1pE/fXVZPofOQ5\nv/f3iWYaIQD+RbNd967PbJw3cBmcdr7J8SsDC5YZgsjALkLCS2/7BGG+K67W\nU4hKkWMRCjSj7njk8SH7SdiCq05gLTVCBmpOT3W59rr8iv+WdLtZC9cpLuzl\nLGICMyvQPX8rOKxLek0na1G/J6W6eP4ZBj7LXcrUTjuU75rmQDIi2c8m1+cy\n0qPtLGTLExBY2nqsjl7O4rAQd54UT8SHjg6aN+dnzhXmd75PB0wdVLkq53/W\nX+7RoUmHRCBdfltOQLm41vLRYeiIe1gCTjinGuq0F0Hav4YxknUpXS3pT+Zb\npRy0K8z5Mnq6PsLku3hpOcY3+OqKIqclh4JKIpe50oANZ9tQQ7XAtBPRa/7o\nBrVKhXlOGJ+/m6PyOG8lQku+wJRI1ZTPKr7XYe+UCkiV4IQy2X/jIwXbwz/E\nwMbm\r\n=Nbll\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDf1W5cn0Q3oHtDqyZN20KTKfVfRe/d+aVhVLwC5U1DGgIhALRcwsdqrE2ZyDrt3PCBVHClJY6t+LyxH14QBD4Ixowj"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.8-tapestry_1559702432604_0.5204776167597027"},"_hasShrinkwrap":false},"0.12.62-beta.0":{"name":"teambition-sdk","version":"0.12.62-beta.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-beta.0","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-sJM8et8FoLtCtvNJEGYsdNPvgUjrA8HmQOsvtX5oYzjVytC3hdl5i5t9QHnZO9/Isc7SckB0S1zLUpQ/L0QPuQ==","shasum":"8426f3bef8465e1300a762c66be5f0e2e45f34dc","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-beta.0.tgz","fileCount":434,"unpackedSize":915144,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc93jSCRA9TVsSAnZWagAAedcP/1uA/Dnjglq9mvGRRGp2\nwvI+B6IFx6ay3aM652zoOzVhpbLJiWtWD+pYQiWhyn6CuNIV7dPAe038JnVu\nQ0EHYJLRmijxvtmsDaCLZ7lhcTenD7jlcyfp4N0iZR2yI+Cdn0R/8GD0Jb5U\n/mbXAtAYGUO5W3faax/Ih6Kz/+3mIgmfSPMfNS7yFUjDAZ713Y/8dXGZJ/EW\nPQwTWqsS6vdEMoZ0OhKfQxzYFvKQOqAzbkdxXRO+7WBR85lQT9tIhFTB3Nam\nFQDG8wTm1v6zSFWnQieMDGdr7Ig8P8E4K5bbIFHrawwIjyZMdd9AUZG8vcoF\nqlIk8RMI0LxaR7xQnOsHoeDN85p23xZ1KG60L+YyKudzde5WmDgp7MVia0HE\nLOgvKg/rN2K3Wz/xGeBNh0UFODD2GUXFNMGUtR5etlO1+UHJeYJu+O9tdsUC\nZYHyfeQg/NvW1aVfO6BTFAyTUomijEjzYievei0QczURNf2FkB7FizEGirMD\naFvWniauHP1Sa1Mu5AiwCog6sCWmSQ8a2ODSp6dMrahRCvZymNva/Kaiwnvz\nNUXEUo4pfPtzxNAy/8DxDt0MEFwG/cMVwa17LL4NQwRT2f4FSG+ZfYrCExUr\no4VjW28G0it31OxXaWT2Y2buJzKA5u9wgC5WTLd8XYCA9JWOQPVkIc+aidSh\n3m+d\r\n=kh8L\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCROoB9etYbgvazxoRfL9Puwk1G+dAKvCmkS1BjSwcxAQIhAKcOqePpR0G4yGVrSK79B4il+9dbKM3f7T7oneX4yB98"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-beta.0_1559722193202_0.5090258747337177"},"_hasShrinkwrap":false},"0.12.62-alpha.9-tboardrev":{"name":"teambition-sdk","version":"0.12.62-alpha.9-tboardrev","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.9-tboardrev","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-2IdySEKtW35im7Mu6RYUOngexaRlRB38ERqQ81b2/g3XkkalsZ7oRTa81EhzL2rapfw6JMhIvrRaSzCawkP7vQ==","shasum":"eea88914ab7d249bb38c36fffbffd23d8c7d61aa","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.9-tboardrev.tgz","fileCount":434,"unpackedSize":915864,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc+KivCRA9TVsSAnZWagAA3PoQAI48KcGX0iiImNSV3/RX\nNFJHFa9Bug2M8STpFFxtcnn/Fqt67rcV7Pt4ibTowbG4MLQ2bRMUxDE0B8lt\nvQjZI9JfhvGRef6Nqt1QbHBIiYcKYmn56woVedqfE4nwmuM003BZCPcib5xX\niyGTNIdtFeOUo7jXuSmlo2cSdZBcqXkODUHVMGzeZA0MBO+etM4wIfRJROdx\nGUFed6sCE11WDUfNuc2gMdqibn5vPb2yJX+/X+DvLM6Z02m0zJ8mNdrO/h2Y\nuC+30meek9PtaUp9vggMYObaT4A44ZNSOKd6VFENPEZx1J/4MLdNxQSQM+hf\nl9Ul2o+tICtL5xrkunokdEqBBSSnYlmJp4FXyHCdiIczlLKNJAznqqclDdoW\n2gYxyDZlJ3gfiMMLQ859KiVjiapDJGJsX884rIKqi0FVFTnvzuj9FJH0kXgy\nSWuVWiMzlEznanUMpCWTsyXSWT1lX2TXmLC2UxgEIujELwy8eUXwJWKYOIS8\nfo8BY/TqpNQit8d79dlhK1Ygfi7Od+1qIVcGc9dmjPqj7Ar9DuKOcJB2XmV5\n8x2ObDPflOjiP3dXdj+Ei9Gib+AgcRhU7ngKQeQw1L23XkqoZn0udyVVjU3m\nygu79BwvH6xkdf4JDlw8jgOou1HwCPVNrRi1mACkdCvZIDb9o7yHlRXncUnD\na54/\r\n=W1oA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB0gNdjNQlI4vncvbnDdVnFiZhzViKAZsavJfdhqDH4xAiEA9gYqwhdugheFQxuXDKX1wGep3z11RK3rTZJ0H01dJZU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.9-tboardrev_1559799982702_0.14798355409645825"},"_hasShrinkwrap":false},"0.12.62-alpha.10-task":{"name":"teambition-sdk","version":"0.12.62-alpha.10-task","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.10-task","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-Tl5ax/5/1BtpDUoF/VDL59IbvZS1CiqjuJpJKknKcGOL4ZRvYrFLCAEt5C/NqmwqwjB71vioEq1x7/Xv7uf1Mw==","shasum":"c980c1d8afa9ff4815d226b6085031d170896fee","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.10-task.tgz","fileCount":434,"unpackedSize":916238,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc/grLCRA9TVsSAnZWagAAQPAP/1w5oJoQPugkkKwjek0m\nDtuvbOMQBSbGSXxdJQfDOuLg/WBFUSEg8eAwGKWAJBj6nC4HuMh/ayE22S4y\nUlRMhiQwpQKcwDGeM4ZIlkGeY3AIYWmq2dEddZuamig+bK+Ydc2obVLCKQ9B\nPwXV4+kO44xXj2O+JEVxyG3hg5Zj+s5aQmWGEU6w6tZDYzmB+Cz6GJFNkgi5\n3ERGaqJ7IkxD7safm24DLCx4QXR2o9LTrPAboTAok/S1Ir5rihtswj6MCyFI\nLWGOcURuQrwL99yAzxphWTGAguykCAqj1YMkHUw4gOVbAOGnwj0gUs+iDqml\necB0bkX4OQpxbTuzf/ZMCAK8xWA0TShV/eX0qXWIiUYK/LUR8ZlEIU5rRqwR\neal+7daC2mbvypXhNwhS20uNpdfuaylDPK0T/e+kryb7soAMCqUQnisOBzKo\nu/fhG2xFjj5DayA6I0lLIm49otgGA5+OdHSh6DiaUZOS2sa2H7SSBvLBN6hS\nws+6cLsuJsDsTeEhrTUUVC8ARQBOVydX9LqjvN6l3t0aiUwMxSRbp3tAtX3D\n1/LfaCpAU4L2kWmvDrkYpPI+BpLy08MPIePdZyIE/KIG487+5aqUYUY9RQb9\niq3OZw9w31t6UHYoVngmm/frRtaIACDMa+yKpGZzDfDPA9WizL3jV2G0mFhG\npLUm\r\n=Pbr1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDJ1y4hVORqIUOCLE9bdrZEMsn+GvUsQt7yyocLQXAeSAiAahPoOcQVWFQJnmW/Lp51Dzdvf78Kt1vpjv+T5+Jd5fw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.10-task_1560152778643_0.4290413446268757"},"_hasShrinkwrap":false},"0.12.62-alpha.11-suspendproj":{"name":"teambition-sdk","version":"0.12.62-alpha.11-suspendproj","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.11-suspendproj","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-XBRxWAblnHEj19qPgZY9SKp1N09x70M3E457lfcenA0xlBL7/7x2aW7YQbBpqcYYFZbu+rBn0kGLhFli3BZhDw==","shasum":"368b5ae4d33a08cc5c60c6576bd2097084de3941","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.11-suspendproj.tgz","fileCount":434,"unpackedSize":916712,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdAMTeCRA9TVsSAnZWagAAd6IP/jyvnsO4uDJXpzgjmARG\nqDST1xvaGMhuZRIJzCBqegJzF1czfuMK6N3LTbHIv49fhQMnGu/ABqiDNJmJ\nS2GnFS0bE2aFQX69VObKAoFr3DY/6fsKOadem8HLC+1tHAoP4VPBqf4OyN0Z\nXDB7FLck5eknYMiaky9BrKEE/jZPqVgoRwVsz0gzReGV/SOj32ETmnx7S11+\nitSupL9AdD1r1tLvhVQPJxwcwmnds66rHJ51XHBonHOub4AmO0hF6+RJfx9K\ng4y3ZmGXD99Ou4vnRpKD7Q+RKdgrDS1MEYzRfReiSFkhRj0ZNmFxFmDRS7rq\nay/PJ1+WtFzR4UJWer05/V9EpOCzClzvxG/b3dyUUR7StqyT2CguHSSas1j0\nSLE8hQHNM1cfnFJIP2eJ+9ziNKUJEXw7u0TOiRGqxmhDOee1iAcgSxhvFCkA\nhePXy5RCdtEH+1CHVGPvcZqgQBhtsOhwq9VH57QKSsbgLnuEBF46yiYvJH5R\n/4pKzkqT0562ps3ydL2svRCN5crF9kQ8KVd2HBIpfxjc0ubFYPI7aw8F5+IE\nBSW26cveZzugEzkHE5DDcW+biTuqrLs/2L/rjnbYI+MqYAtGa6u4Fkwxo08r\nPGLhr4WzMJZ6/rsLvVP5PfdpyafqPwrcDzHBkH8rKUJhixeRN+83D7qHIhbk\nENr0\r\n=eotL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHJuLo/5R7jk63QXvIyR5pyQhLwHx/0At/+oQKR3UJSOAiEAnwXUX90P57RXeiaILFp7mfkQToxE0KE7AIbMRvv0pxk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.11-suspendproj_1560331485317_0.7556126780201595"},"_hasShrinkwrap":false},"0.12.62-alpha.12-tapchartname":{"name":"teambition-sdk","version":"0.12.62-alpha.12-tapchartname","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.12-tapchartname","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-IsKUmoWAdt7DoQUY6fGeeeB9uZd3nceVIHyLGarodBMzSEYK+u/cNkXNkx5QSV94OwgJd4rzzAj2Z1AVHoXntg==","shasum":"b59c09f14c7b76110eb4988aea0272752c00e721","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.12-tapchartname.tgz","fileCount":434,"unpackedSize":916736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdAxlVCRA9TVsSAnZWagAA3pgP/j8yyApSj5J+62mS2Eow\nB/uhynqDHKd1dB++KYNGP+Fv3ZKbJFNFKt8IQ/K2vIzTKA2Jdnb7+J7OnCiM\nsHo6+y9xMX1rH+y4uj4cfeAg+wgTkQR9Z/IsMcX4Fj2LoBboVPrGDnX0wXSr\nsUCGQTEVTmpR39k6NH6L2jfB9RlBL6/2BJ5Vpu0VuaFbS/EPX7pRqkTkmKXz\nwYCKUTcnRL8O2flmExk/s4riqV6L+CFWkNogKmbvFUaPR9/HnvMDQ8eeK6i6\nhCOUsRbGjrELitcqDWOncL5PhqqiO9tiEDC+kzKEX/4TnAVRKT/4XuVCo7X8\nUpJq2syNptVXh3DLsPV5EM01IQdRf1nvTIA3r6F3UvNJ54GbpJryC1uQ1aym\nh7u6O/78QvENeMZ4acolqLKC80hapyCtfq4ZIJacoqTdtlfDc+x84k9TE7Yi\ni+fMR1qx23IkI0tb3fzUGFHrUvPYmc33edDvS3ZiHYeq1DatYM/B2H1syU9c\nfJFwLzJQc9c1Qv2WmUZqXndqrvK8ApUQFmXnpf9sq2Z1W5zYWqPALGLth7p2\nPbEsgun966RE8f7bHbqfbj+k7MiRrLZ3KSo8WkvBgD0VOV+GtzJaqRLDsGKY\n7CIJuhNAed0z+QmAwbSpBxzV7EGFpFJyLKY7WsxdkqUqWIKef5EcAAmzvt/N\nBbpu\r\n=d8Aa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHvFCEu1ranuo2lgPGI5Q+cedwUY3KKr9nP8kf7Tk/iTAiBxSOhmt5jZcjsCwceODDuU/AGZY5CBbUwZr0lxFAj5cA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.12-tapchartname_1560484180259_0.45252957839586694"},"_hasShrinkwrap":false},"0.12.62-alpha.13-tapchartname":{"name":"teambition-sdk","version":"0.12.62-alpha.13-tapchartname","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.13-tapchartname","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-0g8UZfAtKa41bdsgi/0LMVZHf2YepkelZ0ignEhj57h9VHIMxNR2mMN2kyJWCCdmTb8Sjxr5IHHFhtDRnKBOcA==","shasum":"996139fde9e68a47fc20349b9dfae8c1541d3dce","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.13-tapchartname.tgz","fileCount":434,"unpackedSize":917116,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdAzkbCRA9TVsSAnZWagAAQJMQAIu8nUNTQCIrWGpCTl3D\nc7hROBz2myQvUOb+P11z6+QQ64sHnnAajAM3FEGmklXlvA7+7Lc26bY6eXRa\nCXWjF/QyhReUv/vl2OrsZMIqR+dPVqoneGpevOepz8yoqFbquW1NsGw9azkD\nHlbYzTDo5HnlM6ugnNIAwPyi/Fqdv71HlWqXwPQxNlAkzYv/pvbJ5Y67W1vH\n4kUPQv//aPZLVmiHxDLIVqscfxLTr0vIAw4XMcyGNcvGdUbwlOe/8AcBP8vy\nlGNwitZDpLZSXFTyVaaTCmfwYrOiBlFsdQT0En2rE3ktfPFXZdNBgJQaxiY4\nfPr2r6aaU2vjDg0ULkRItjtQNtgN6pqVXMkzS9S+h/pP1vjcNqZpzc9Kqw7n\nlgUlmSTVqkqn0MiI6KE1n/NHBk66fzJq6TdhmVZa1OcgvfxSuCAaBLqzPEbj\nffAnvr7KRu64PjzZYDBOAuPYpBJWWm/tfOW7lqDYfq+mUTFKJK1cz08BtAY3\nhp67O3Qn/G2+tIgp5CDjAwCP4U57JfQoHxwAgejIUP6/Aj8QIeue/Zg6wkDN\nIxal5L/d+eCRuztktmqEMhPa6RFYVU4JIFwmWpR7IwshiLJG6XAhTHhTTZmD\nmYSqwCCmagdqFDfnUcsgLlYi/dzIBJ3FP9Re4bd3SUZieby1SeSApUf2c7td\ngtUu\r\n=d/dH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFDKMqtT/b4VoOUu/xPHL/+BGpbkwBwRr/zwBZW3UIv6AiEA3UZz7C3lPUrVVkeVAY0Z+SHhDsFVbr2MvlqqBKzOO1c="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.13-tapchartname_1560492315185_0.8761984711139641"},"_hasShrinkwrap":false},"0.12.63-alpha.14-tapsus":{"name":"teambition-sdk","version":"0.12.63-alpha.14-tapsus","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.63-alpha.14-tapsus","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-vGwlDL+4WiNqv8L97ggQ/S7Wgtt+DggTxDblGcDYxzGYShra6xfsYnQOrnhaN1+ElRreUQqI/3l20ojI7UNWKQ==","shasum":"76d5058e4c784ade0b1fda743d21a7819bdb97fb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.63-alpha.14-tapsus.tgz","fileCount":434,"unpackedSize":918688,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdA081CRA9TVsSAnZWagAArkIQAIBa6UF1fpJbkjEGarEs\nx54wvvHgwj02o+efIgyW8IFoViNW2gjXT4iDciB/jVsTCRHWXdQn8g0oohgT\ntgU90NYIZA571SV54VlT2QMCwINCVS6WXWmAO5g+SnRkD9730gy0D8f6SE02\nbvaFgeBV+G7yW442TRLZTg5YTDmbcRlaU2udi1zsHVVj+fYAH+wt3iQbc2H0\nq/9PKOeK4vRxkMt0VXk4lY1b4EXhELVAmkuNLJAV8Ib0n43HyvyhyLzEcOb8\nabtEwiV2Lrfetc7T/HwvL0CuH8BqkeTKB69vz6hVCPVW04cSGNviIVUDHVB5\nlwv7wZ47w94tMfWw7McK4RFLMcMLiqpRTwu6jS7WfJvhJ6BiTT1bI9mLu3Sb\nZyFPLWvRrQPvAZkvd31gxLQ7xZEbxhGKfRjxQ1FnMopka/x3g6w9RU+EyFxl\nFu5J1k+Kx7OGJvsnYa8eZsz7jHVlDfuSEBn6SB+Xdc699Mruq8tSCAiRMMMe\n24Isy4Vmda5jTWHxaKQq9APT4zRqD5ESv9e8ToU17QNDff6vkRqYJIvnYocc\n8CSTCpeZviBaRwmCUj4TPWahZO9fJXDsCcmxaG/e26s/0ePKhL0/nQxuZiUQ\nA1f4BpZV+0LonnplEagHHosX6aAf9SAk4CwZR9S3ZkXaEMc5JjDezzG+F0j/\nTylG\r\n=zfz9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5Mt7Km/vZBB3jtMu345itdMJ6NITLZcHMtXGrsnlUggIhALwt3LqLmLHO2/7lH0Ed/KFBcLGh/xmDOGj8jiong69I"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.63-alpha.14-tapsus_1560497972371_0.5495717755484981"},"_hasShrinkwrap":false},"0.12.62-alpha.14-tapsus":{"name":"teambition-sdk","version":"0.12.62-alpha.14-tapsus","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.14-tapsus","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ohQUC9NT8mpnTLWBZ0n6sYeB9UAg8JKKGXQmyS/X/2mzwW27lumgYCP5mfmWpyV6ni8pImI/hTrG0OCyAGsKTg==","shasum":"63611e65265608020d6edd269b26331ccb5f3c44","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.14-tapsus.tgz","fileCount":434,"unpackedSize":918688,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdA1CzCRA9TVsSAnZWagAAouwP/RoySTczgZr65k7INcWu\nBEwpmPJShbrclVm3tpvU1oTigk0BTXHO8E7Ij3gJhi0RxxYTNOICpFSypm54\nZgku6IP9YJ6bR5EzWTUy+efKr21uAhAmagzjFWbZ/omsbpVZ/DbocpmWAsbQ\n41YXjzMYU2RR6hNQZ44lmGQkDsq0CMF5AVyNlRPJeXkr88J0LM96d9H/bj94\nmO5hrALY+uRWoIrmU68dtg+KX16/je3EQchPwsCdtWXGQ6P3tYpRt/0zZm+1\nUfadDji0J1PnPXXEgG/CCj4pi8LnCr95DTv3J6b+QUZNbyPnF4Wl4p3wAo0O\na2zx5sIBZJq70pgnsrz2xPwnU9T2nYmBdxYyByHtFGJLoAjXX83iBe05v59/\n3rbmI4nVxXckWHJc97FdMkme4plPSpgrkcrwQjq+Hy0G28Defi6aDFOOrwYx\ndcFDgVvBJujpmtUZ80ZN8+xthgcwaF/SUS1eI8IRQPSmf20rEwqTbGZFwc0u\nkgtSOXlaWVoG3rc+NBL0pAy+rrr9sajC6VVtAZ/SFfJru7Kv1PDee7OWItrL\noNO+ygvG/7/7D+IIXCluD0EQxFsFJPspomG1APl/vvx66AjVQfOeYTevpyMP\nm3OkIXsLbk4riKhoVRgR/UYO71hPePNoRMdhztlECAUpz7p5xF+AjfUVOS3W\n0Ybo\r\n=WUBN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCunXJDmLv9ZPVho0ksEeh2mjpCn49CPf635ye3kqXU4gIgUwVijl71Xs9joGmRa+W34ZWd87W3CUMzMEJU/KiiFNA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.14-tapsus_1560498354830_0.07152474052206559"},"_hasShrinkwrap":false},"0.12.62-beta.1":{"name":"teambition-sdk","version":"0.12.62-beta.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-beta.1","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-GSmqwqQWt+1D7cvfZDEomwwY56HgpsT3sAH63shp3tlzKZPG4U9c5Y0WS+0LCvm/4PA4cBs5cT3Aih7GRw93iA==","shasum":"e92ded63c2436955b38774669a4d5b0fd729f565","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-beta.1.tgz","fileCount":434,"unpackedSize":918671,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdCbbICRA9TVsSAnZWagAAAaoP+wWDmzLk0srYq9n1IcFs\npFen2qe0bOeqc9uWTIHzWjlwpRLBo1UOACpc708F9MlZOryxl0TSCu2YZgEr\nILpZkToX6Ca968Ycar3YpPMZj0nVt6ePyzIzbnC3aRIudY6D17XcQX5BaVNa\nNjfTdoVL0LWZOKsyte0sYPH2hbOhBM3ylOeVYGBkOWwOER31CVlI2rMiT8Km\no9sl95ftgXuVyeVGs8JUVWIOwQduGulAPVk+TRXOJXqKU7vrWH6E0ylAY4dg\neyQv2JHoF/5GX9RSFEo44M/f4za0fiEzN8S/9M4/WtZzu2wG1mRjmL8BAA2g\ncJJeqUJOL57wMEN0Gn5y2b6QYhe8ws6FcXtz9+MO2eiPmWbl0qSjrcnhuyyn\n1+pd+N2YZLNiOPyaEmX0YVYQ2Ofn6FnvfwL9/IcQ8ocqoqHbXowC7I5ydLfq\np8lQ/CZSP4LKoRue6YgxNGLKc19ErWbByrVZBYa6YvuudrxbXpIDOUu8g4hB\nc2TxXZt/+fMJgcKgR4BCEzl+PmdvU1ctx3zZUcHrhFdM9UNUxBdLef2wiuUO\nFEL4n7oBxk9C/cuBOiVTdLFhi3cjaHXbPiYPtxX5hP5z8b3/vFMpwy+tlinG\nQzt8CyYHyejwC8ADxYMWEizub3+eyHHeXzURrPI0TgYPomCif7iSQ9faZqbI\nvdeh\r\n=SD/R\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA1bcFeWiPdCwaPcFKWo8c6KpfMk9c/IcsYoLneZjdJNAiAXWTS2EtXOYkMsv1mVJQ53M/T9YHFIqTUpPWnPx6jWwQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-beta.1_1560917703385_0.321291412427573"},"_hasShrinkwrap":false},"0.12.62-beta.2":{"name":"teambition-sdk","version":"0.12.62-beta.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-beta.2","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-ly8ud4KQ4wdItycSsGhyywQORxnvhi0PL5Q3XWCjQoCYINJSTEDFX8Zk+nT67kQukZ8u49npvVocLj7A/BOF3g==","shasum":"800c334d1338a39c27613939bd0e1bd569facd39","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-beta.2.tgz","fileCount":434,"unpackedSize":919380,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdCbhVCRA9TVsSAnZWagAA0GcP/R1NMIE75mFB+9S+aT0p\ncRR5WvkBZ6ScuiKbPLDXksTZl/qWAPUwGfFwxMYwJuMxrTpoYmR2D1rZZ6V5\ny5YGt8glD2TPi0bkUHymPsog/0Fx/wjhQRjzcgMDPy2ERwEQCaOAqaNYExRG\nqVUb0/UaV0ZvVPXxygYkcDv+POUC+LnWHPf3VAunl1OxAjiq85ChpuQv2/rI\nH5/GvRI4hOYZM9XRYLdMw4fEHAWDQqTTIQVAHpPwkPmwz9kJs7iL6IF+PVU/\ncIwMU/SC9+UBc4+dZSzc+/a9cDU78ULDs7yxx8MYoCIod51A8AHbKGGZGiOU\niiMHlK+u0BzqvvdFjDwOlGjuhZAq3IWeLFep3JG7CkSz76NfbhiMmhmLdC/i\nZlGOseCGgTK4EW0SycbgKYIjxg6yFNY+zCFN6Mo4EV1j7/8Qz0Fs7DIDRV94\nLShqgKhQfAdWLywX55Smzpm4HRoMYEf2qIpAsN8Cd4/EPjyJ1izjokXRrLWS\nFfUCMfJE3erf+n4UaqEHY3C0BCGeKX1/FE38Y93B3SMcWrg0XBbOWazyjau3\nnqdGiduaOhYUGsdE9cm3luUIpNqBFHPDSjb0MF9ynohm9rK65zrztczwfyt0\noVzSXNsMYDBRl1yME0g93Bf//g/zjHmROQ9XLRYVMdB9CYIcVhTqqS6xg0dz\nVbsJ\r\n=DPQJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFavN3Bz/dU9qpECq58iSrTqJsvmqmmNjkJywhmk7MG8AiEAmCspLRuL12J1zx25lhMQJx1/4hzGerViT3nYfRqD4Sk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-beta.2_1560918100810_0.41592277630294894"},"_hasShrinkwrap":false},"0.12.62-alpha.15-projsus":{"name":"teambition-sdk","version":"0.12.62-alpha.15-projsus","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-alpha.15-projsus","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-I6jukAFNf9so+EL9x/6yjCVD3HCMsBWEEcoQniDlpCj6vF1Dn1BGe0gjK63t73OYXLj2hjUaOTjSCa9W0WXciQ==","shasum":"975372a8c0c49bddcd30b3e8366f2802130b2fd9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-alpha.15-projsus.tgz","fileCount":434,"unpackedSize":918693,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdCgG6CRA9TVsSAnZWagAAnoUQAIwofW9/xqhWtsREVyl5\n4OQv/NvKAZet9tombbh15SX8707AoK1GzMpXgNVBhroca19i+MT+kmlaHRQ/\n9zGqeri5fgd/PCbLp53VGFRmtsf6DptGoTleOUs50jVM6q2kWvX/cbqSgZfR\nS+wIooGipxnmupxnCYNEhh5e6wF0purhWLPdE/CkDRhUARbr//u3J5wGHbUp\nlIV8ZPmtoKI/pPN27mNJVgYN1p5yRo2yUmPbWTbhtsj3MuKUYDLHXw6qCTj+\n4hrOGLSjE4AnuudIemKDy3AGI1Zdb2VLLcTThivTXlm3ZGfhlC7M6UQEQFmH\nVnNinUfdwsYk3sh+Fo6idwUUNLJO79ntMhycKGR7JXslIORJW6WnyE8hRhHL\ns8eSyulKqzSUMeYUqQuR07eWSJ8HKJnksiy6WJnUqq7zBUZUTziy3w6THmEy\nay/M49XOrVxgnQAUXUYfZBEVnmiw6bJy/dFguA9LUHcPmwUj9MiXnoMnKCPP\nBuccaSJk4I4rPYmd8yurunpXGGcBNctLs2HhOzyybjfMHCT79s5dui9dhcIy\nqGuw9b/znkgtBF3jWGtN/g/g6+/l7NMDM7U4ASaKcwm8tWgRAxJG4pVUGLi+\nzbp442lM+GhYwURV6ibDFHC9XuEMEHsZvpUgJS3tgMvkmNUQfTvYkNer0tXf\nHAQ3\r\n=FavA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCL3zBPjQYrloY4WnA6Gtqd4SDr8kcO1ZCieiCb8kUEmAIhAKmO2erJmMIXr+VOh/VwXSocn366gTjuAcDveVp4lmqo"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-alpha.15-projsus_1560936890049_0.8030158048944247"},"_hasShrinkwrap":false},"0.12.62-beta.3":{"name":"teambition-sdk","version":"0.12.62-beta.3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.62-beta.3","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-fXeO6cwvfzYG62THHhqloXLc3oU7sLkPys5jYw28Fp0dF5DbZvgUd+ULuhz2ViD/I5XotpB9pUend5P9vUuqpw==","shasum":"4657828f2bf0924a1f6889d066926f852fb94ba5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62-beta.3.tgz","fileCount":434,"unpackedSize":919392,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdChgSCRA9TVsSAnZWagAAbu0QAJ3Yn1C25+ooDs4wJ9sF\nHblsPw7KipWOQV1Q+CoX2ulHiPHhku3lb6Eh2Jwd/yZlmTIGx0c9QGRzIqN2\njazCcYwAWPrurgb1uOk91jDmCSLVyxW4189vJd1Ii31f5hp51DgqNmY2rnJV\nquRRrvpDk9BhsgYbr2ya4ElWXiPnZBMIPbNgs3T+G5xuUdS/Pg7MpueU7LsO\nwHMUZcTEhNeLhhBbIEkM5HSzsVmYHyjJ1AA43OFY68pWCgywdqeysn6jYqQ0\nM65h9GH+jAGYecHMMN9w+spDxJGTsjQshS4PWFSlzqiBT1FseQ9vDdOkObTA\nXgl5rUNyap5kapE/Y0Ckq0EO/XYaKquA7LbXATgpH4oEH6dWggNyob6IjxmP\n53ag9WA9lUnN1lYqY76grqjBCxdBXcRTtmXVc2OZX9uVM/1SBIBkWB2oZbrn\nMojHGD41siAaTbp3i42xt8J6gZLOzELWA9lbv3ZQKIdPW5VFycMbwNqoFSPJ\nrD1Vr6gGxTFEurAEjS47tfdxZUO/lcn8x7JtV3yL7ra5HBk6r5CcOgjWT/0B\n9EeMUXEkbFNPh1753f67tfpqJ6hmBX3efSrLWChzgO4dgEXFX7XRcIcep56z\ntCR8Wy0/aY5mVA+kkSETB2RWj/N8H3d38e2eLZ1aVnbFeCCVKNSgHhFWNXz7\nzNWY\r\n=S0Lq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID2FWwZNXhPdJGG5jjNcIvCFNf6B3uo0kS17feUhjp0hAiEAokuOXZ0iGTC1q7jH3KmMB2Uhs2UvORuy8ulCXlUj+2g="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62-beta.3_1560942609892_0.41606298296108934"},"_hasShrinkwrap":false},"0.12.63-alpha.15-tasksortmethod":{"name":"teambition-sdk","version":"0.12.63-alpha.15-tasksortmethod","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.63-alpha.15-tasksortmethod","_nodeVersion":"8.15.1","_npmVersion":"6.9.0","dist":{"integrity":"sha512-wDtLKXn62vyG7yKSJdeWPqqUHkYl4UBwc5/SSLkaDKozoKHL/ayyK2X+AfiLXJNAyqQmsweqAkLGahh/aP6aTg==","shasum":"9b0a59f38f7eedd5a5b0f90852ebd51371a4a352","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.63-alpha.15-tasksortmethod.tgz","fileCount":434,"unpackedSize":919480,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdEYsfCRA9TVsSAnZWagAAag4P/jH65t5Ny0HOSYg8HSNz\ngyx4HqAYBqF/f83IreBWog9nuMnbScXokh9Yhgir7PvkEgisOfl1sQuoINFh\n220CKLVWoF4n+iYJq1wKZmN/AR6CvAWNXQSv4jabuNpbq0jZ3tfgsM1tj0tU\n0gYR/raVEge69f2ly9ANU0BpuY0QNZsG8dGEOClxPRX8/OTe62F3fpc7JzMV\nGWwEShIFdAiQpJFAANhp8fY4YkQuQitJjTBFIe99M9LuMIpP981Axxn3dohx\nVK9EHSVK1HOrN/rQiATvnAqF+IlfvUy6ySqUYyVY/Wrz2SOPUMOL46Ck0TYC\ny5XnhdZk5oTgLpSZS6XiVmzvpis3WFEE90Z9+KqrjEU3D6Aci/B3U+0eVb37\nXMD59zfm+8bjtuRxluQI6IPSWdppaw8r8NpdWQdPn4VNboNth5jTPfaz6Z/Y\neg+ThCfovCswB/JKRgzeqqXubDsw8jIqbY62D0wd/wJgQ6N330392EXTlVny\nIeOy7Xb6/4pFh8sKZGkueOL20JKuSDSHnGk7YzlQn//X/FIg14/taXW+vykn\nStr2qOZ1w+PclvE9E86vdFznMFGRu+/BdGIRlCn0MPlUzx5SIUs0k5gEvw30\nLXq4a3eq+RPHjxTHGDYEAROpAKDi4XZFEFjWF8GDWBUCD5cwZ570DIrmq3Od\nQgZ+\r\n=Zwtf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDCL2jQLVC57GFxamOxpq/eLD32bxsQ1cGhdBPXtvh/wAiBZLI2t3mesxp8VD0AI7yebiF7SAJemAeiajsyNN2mCWg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.63-alpha.15-tasksortmethod_1561430814859_0.27385721620669345"},"_hasShrinkwrap":false},"0.12.62":{"name":"teambition-sdk","version":"0.12.62","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.62","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-tVhPfw3cm/M35vnuB0ixZ+31D+zsHfCNEznjnMZfrElIw4DEMHzk1BbCzjHlXOJKCxnr0qXV6ZMeaHMRro8R0g==","shasum":"58da4cb4d0514451622a800fc4ce53d25204b729","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.62.tgz","fileCount":434,"unpackedSize":919385,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdFCkaCRA9TVsSAnZWagAADacP/1F1n8MXp1Rr0eposoa0\n3XFa4MQgkNt5QcDLNXivvGgPBtma3MCI0es9VzxFUpQF/RNcpPCChGgElCwR\neRUZTlmuD8w4xIMxqtuJZf4hkPVlReg+6meENy3ppqva9gfP96xAOvvtcmer\nqXXPAoaGRnjqeJgFL72GF90hmZzFYntu6H8mOZo38WP2wGuEgyr29HOTZW/7\nsDr14UfZIjlvKhr9gEWO9QaXUqseR95SJpyyvvwMdK+mpiy2Ruunu2xLlLFA\nq/IUgcL7LEFlaowtfvvNfFmpYIRt9c032nUs1OvlM5PYBqPSo/A2eztAcS42\nroZKNnnjKXjCyOj66VANE0OFKcNPZDPXhf3/PC5xQEEL/9SLcDxYzFU/Tp6Y\nm7HLxMMrJkmLoPMy2Tb4QNx01Z5FxyTi4hp9WjdYz5kRooT8Azz2hu1fiwGV\nlTPviM+de2idumom2/YScUaVu0fdBbiqBZHsWt8eMkeqmXAWk6OyqvfuLiVu\nTuIaMfMWUbr5Ezmw30mN13BwPovQBELO1Y9gaMe6vNOS0LQWiL3UCgRyD87S\nlgjOI9jNMwvxV/yz9LYWtCfmmGBij90AV6qOS3zIqIkIXGlyCH256De93Jvc\n21JKCOVa5zsQRwJd4yPKlONm7z4O8M+jzziam0YXD8j75dnpzXkbOVva8etr\nWrq8\r\n=PhNu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDcVDyzhUy4YnHh894gEBJb/6LGKavzfYjQiXNKqgNuxQIgfIYzx8upwlCsaLs4IaGWpPJPmjlecxcm8Lu73yBOeLc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.62_1561602329622_0.6564725058277532"},"_hasShrinkwrap":false},"0.12.63-alpha.16-alihttperr":{"name":"teambition-sdk","version":"0.12.63-alpha.16-alihttperr","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","http-status-codes":"^1.3.2","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.63-alpha.16-alihttperr","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-fTW+BGSfeV96gTAHLolOS3WY93Dj53gWZiyoTc2fvWhPGndDepvLAfnbpuSKtV1qDRpgDIeXapI6NwO6Mnk6kA==","shasum":"3169bf9d878e5683f30b285e1dbaf93cc8a9e4d9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.63-alpha.16-alihttperr.tgz","fileCount":434,"unpackedSize":922060,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdFCnJCRA9TVsSAnZWagAAdngP/jLiZntZ3MzTDWcnsU+H\n2CVaF9p3O/tdF9XXDgnp4FWgJK3HKyJ0H3a5HTWADIv9Mtu7t0+xWTLMysGt\nepdFq7imKSisUh1rZFk0ht/7Zf4SYTj9nXMAqhCcNROHvbHp7uAcXbgz/FW6\nC4rk7g+c5MC+eGb570rDn8gI4rLbJA2US8dv6N8vCfT+R4UFGRU07kfLixEz\n2v12Q9nl92X/8PRwjA9TqSyCuVJqH/08NWfeU8jse/9QlNBnUBlFUM7E+WVG\nzBd9E0fEaTsLr7M3+sIEgFD3NbuN5aYUe/TtzGA1kHum6ZdSh6Hdw7LDULFP\nJdS2cDzVeUb0bqwGUNfi0Wjz3IhjI3+Wq548AMeo1wmY3dfS6NS87RGLXSJs\nmqlMbOv36ZihJFdQJy300n24fVelzhLs+3aPP2Ie80q0ugrOUqT6fY9sVZCk\nLJc+dU64AzRlz/MoNnZttTFEOsMMo0kXHnbvl6vuHhf4s+o6DWy/O0htkIQb\ng/CytUR46DhOtIP9xnW1KgjxumjiqyMioMsdxIMXlGhVU+K3pQtOMHTeos/2\n/oVNT7kFvGLng2E3PwEhDWwhU1ESWBc7TcfRm6iL1br14OAJ01H8y72uKvGP\nCk5wPD1nX92d5pSj5dhjBHock4ZGpFVTwLxQwcDNqT+Ob3F4uIIDiq7uBrbN\nZsoJ\r\n=oCim\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAPyfuX2j06KzkHdIAJuhYWJ4ZD2rGhRKWC8xToP7No/AiByqsijk3ivGuelrZe6jNWwVIRkZFqwCsvrW2x/LpGYLg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.63-alpha.16-alihttperr_1561602505261_0.4459854299028503"},"_hasShrinkwrap":false},"0.12.63-alpha.17-alihttperr":{"name":"teambition-sdk","version":"0.12.63-alpha.17-alihttperr","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"dependencies":{},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.63-alpha.17-alihttperr","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-YPHwCVhqj+FM1HA1fdHHlsbgRTkWJTvZlBS5m2z0K/zTTr05R5nw03QrLI/RE5ezKFnMDbZIvZAkgy7Zk5XRRg==","shasum":"7bd8c5dced593e031725e88d0337a792ee2c0fb9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.63-alpha.17-alihttperr.tgz","fileCount":434,"unpackedSize":921223,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdFHoACRA9TVsSAnZWagAAECoP/ijfMPeLoJ3xwVnUvadA\nil9wv5MP27XIQnd6CFfOXJOFuWCaeuHzJBaKr4sl/lqoyAWoBBQrH+0FOnDp\nzuoQuRJYpeau4rzPscBFPUE+BStOY0RGrMjnG8DZ6/oPbijb9fx+7tVC3n/D\nn8cZ+0e5E2ZjT3TbacvWJrRqcM6SKKmY5Rr2hdlGAn8/eN4inJ+kj4sm5C6A\n39RhyK5BCHqG1Bm/HhjK0xjKvrbClvey0akgWPoGoXvx/f3eP/AcLqOCvYHa\niAnlw+RppXpir8fLX+A9Txw3Hd+flWXkc9Pk3qUywsonqjhxPRuTQ+XiMT75\nME42nTtN8C+gCl5/wZP7sV6V+Ucxl/FRq5JLxffoN/L1HnGcYr5mRENvbgKY\nFy84S1iDsJ2WQkuz8CGw98nMUhGcbqfsey9x1/kF9OfQlaT9wi7CumhaFesg\n2oUBPOeNKS1xeRA4FAud27prBQ8FU7pwJIJYlkSRN/Gl5gRao73XPrjZ30Ch\nJurwnspzIeltlhX0GpJfJYZRuirch+kcJSDRrNnfOud5yzG2VDByc5jnn6Dy\nJQTY+DvjJhalQYwKkK45FV4t3/26MVQXiA5E9dwE67kIQapZ04TVqT5RvR3C\nenvlsrOQiic8MTf99XwSm44OsJlBmGOLuuLkaDrx5dIwRplkpPF79hzmfieB\n0uHv\r\n=LXKO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID/E6exISQUotmYmkKyYCsM+N6oF1gG6LgOXtSAHcs+XAiEA//UYvkIJ65CGLwMjJG0vrBU8YHQT33lLV1p/o1IT2F8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.63-alpha.17-alihttperr_1561623039960_0.19253365572647452"},"_hasShrinkwrap":false},"0.12.63-alpha.18-cfe":{"name":"teambition-sdk","version":"0.12.63-alpha.18-cfe","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.63-alpha.18-cfe","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-ebz2rbM73LGFVnCPk50Nvpw/irVPEa8rxYFlru2F/6k/It6DRSFC58yl/GKN14NQ73UZrFUazgUsGQJEiGEboQ==","shasum":"c39c75089e363501ecb2c684698291bcc32d0f6d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.63-alpha.18-cfe.tgz","fileCount":434,"unpackedSize":919880,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdFMH6CRA9TVsSAnZWagAADUwP/RxBsejsKipmkSVNoeiW\nMWJbnyiR8wfkzbgbA3cvzOfv7zLHHIH4L6zkrhsAVYUddIz4XBMjKyzor4kA\nIgs3kvlzOyL01XQ03U3ADsER+vW7jOhfgXqhIA5IKswyA8nB8tE5RlGLDdHI\nDb1twVz+W+aJlFdVPu7Mv7U2iRJegBu7rQ8F8YQAKL28dt5inpF7y9/3awih\ngQjGziEZ3wZlbiXcWu85ZNWFICNbxucR00p7RTJSwIJKNomnWdmLPbvLkJ52\nPvjeaqoyW8ytl6+26CTfC2xNG478P8wkyLHtkqhTDDQqhnIu1FzCQI9hyuUQ\nWgzLoH++5/dsJ4mRnq4AuACwUgYYuclCEleC2n7mjPjIEV8KXZCe3H52Lobz\n/CarsSZBy6qbcInvvNiHRY2QmxNgsgSLCRDFixDgkpTubGATAV4eAkwVE14h\nstxLAwYhGbSwcx7lvcAxi9yyrMKWY4IXWwX1kWy1gTPHAyi/e9NilMTX3Mq5\nF3bHIwWl+EEerMkkEGDESrGcyHeEJJBfz8GTNjgjyyMuH4WhCmJ1rQ0cAhYv\nmM2HAbSXgOMfil+b0zmaZ8PE5Pp23VqY2QLRlqSIsqwnZ5xUBjWxgRDt+dsS\n4YCBp098uMvusP9RUgLY74Mm0RpIZiHV1ZspN6OLjtL35D2skRPiv49ofYjJ\nspnj\r\n=kP6A\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQChud7gO1N1lskbCIGk504HhXZiEUW6uuh/CNxkN1Vb+AIhAKh52haIfOdBHrfBoWr9grdxLqoMAmS4VZQ2cXTdNOTp"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.63-alpha.18-cfe_1561641465835_0.8509794602304386"},"_hasShrinkwrap":false},"0.12.63-alpha.19-cfe":{"name":"teambition-sdk","version":"0.12.63-alpha.19-cfe","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.63-alpha.19-cfe","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-eaTsSsIC9lCU45aS0Mmih8535aw0BdHwoiFZ42wfYI/DSdmHTV2PMo0rnPdwCiAq/a5hqnz/VUoS2MfShNEwmw==","shasum":"bd3ff408b070a049ab607e7529a09cb5351e4244","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.63-alpha.19-cfe.tgz","fileCount":437,"unpackedSize":921528,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdGV6yCRA9TVsSAnZWagAAtFgQAIMjzjVZtO+TwXdY4JUM\n0YKKzERtEj8jwY70o27mG9wF94yxPv4F05fZDcCptQCSZiWSJDdzi//OevuK\n+BpfY6iVud0btvEv4VI4oDVV4hToxRAl+u5w2zrObZqok8iGntm4LJSq6LiX\nuY8wpUNuqMCBc/8GsDT0RIfq2CwVw2OuWHCnmPymlADGZkD11V9VtO2fR9pb\nKXcjFBjahuxXgWE1I0hf5tZAP/SXWbS7u60ywUh3b25dZi7KFjuWTwzopbUK\nPd2vbt15XxHg6qQ4PPKJhPgsbw6EC0NapBCtnobwM1XgrwOOOuvYTqYuDRpW\nYuKYPnbNKgqQVE154otz9Gm9ZewUnCgAttquY7hgykyeg+sazpD5rVe0MsHQ\njRHxu/XfY8NCLjE0k85doObi98EjrhrGFruEvaRVmLIyfxb84R6Vu3YrWhDx\n7iPNVlA7ZB0nLcMpjD3LdqsqerlHJNsrgcSC26wO6/By8htnVF8v6m17cq8W\nR644hEjPWSlcFtmsFzjzWExaGxM4yKmhYdXDnIdckZk7pv9MmNbMzBEEGTY1\nTl45U5Lx2LYBzH8e8zSW1cQ04hqopQtPs5pvLCCstpgdrnbyn0qmb57t8rxb\nV7NzzMV25rPCTKwn9svJnZ3HOS36zlNiruFZvEaobFyQT629Gj3wZzHT/BDf\nMnKx\r\n=bxGH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDUE1H4MQZ44D/Wot17XRyOFDk+SnCS3B+bcdJh5VH1fwIhANQauUz3x2+unVpqODcgexiJ3vsGCqcZ/1AlDzYvX/Y9"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.63-alpha.19-cfe_1561943730094_0.7515099858809935"},"_hasShrinkwrap":false},"0.12.63-alpha.20-alihttperr":{"name":"teambition-sdk","version":"0.12.63-alpha.20-alihttperr","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.63-alpha.20-alihttperr","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-4/VoNbhmVLPQjWxbGAXght7uziI78ssgiH8GSlLljEKZOlPuAwCLZjpBH7BtTNjQx1pShvhEgNaX344apFI9LQ==","shasum":"2543700740e56c09062df08134ef4a93e3240626","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.63-alpha.20-alihttperr.tgz","fileCount":434,"unpackedSize":922757,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdGaqtCRA9TVsSAnZWagAANmYP/1aVfwEoF+KrHTOWMfkN\n4O1CFnQwfRdqzKUIfIMqDAlAF+b+qByCcfw1gBnethi/POcUVtM8KnH/0i98\nuzL7lVZRP35FP/p70+HVKWiSaWmY/89H4cgutP9b+GqEkzxV899wjLjeSaOQ\nI7Dz4j45HojolhwicsTQQESBIXgw9yJgH0Wn8axgmM+pHmeit7OEsRVZ9S7C\n7vX7c16Kie173D5MzTSO1lKmQq6OF5dZXESs6yEuZcetRPY+EIA30vJt2KZ8\nMboEgYcjWspiwtZQEEmVnvJGxByI7Xc6NVwLQzKUbFzxqChAx2Wp1Z/rbTTJ\noc8FTtHnYIUHoyyZl3dsQXYub42jXxK1k7tBWd6xwj+j7Pah+4apw6ul0BuC\n+O69/AiPQNaYyxUKKqh8p7ezem8ltc8c3vymac4f+dTzznpEv7KYtgh9Erti\n/GPOrkY+q1rhk6MlE0UG7KfvsFxYxIhAbtckaZ1/l3y16DhJWhEugnPiqUPW\nO8vk+MkfiyvtoPKOb7iWu8e55n3Zzp3ygpyQbJwqcDqmu4Ehbx3MzFFVP1ek\nxCNU8ef7PTykZMfTVyFl9L1LIs4GRuMy6PWMUorISGxGM3OCL0sXAyLm/NOT\nS7xUeW4rPpLzqMcR6tKPobvAleERN9aoCkUSkxNk4nQ7VuBcPQn6rp7+RhDV\nbLU7\r\n=5seM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCKENDKIgdCR74z6Qg5iR9keT9o5ibQtX1TN5ManS6bWgIgUkchali2x4wr9kCFIsclBrvXldAOafUEiAzrtgxN5j0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.63-alpha.20-alihttperr_1561963180573_0.41613737414144314"},"_hasShrinkwrap":false},"0.12.63-beta.0":{"name":"teambition-sdk","version":"0.12.63-beta.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.63-beta.0","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-jDmdvAjQyhr7pOr3w1O2mIoQyfBNiJJYMQ2WjvU1rO33RQB3yJks++NnqB7hUemurdtFYtxKj1pZV1sab61ySA==","shasum":"846fb8bdd94f147e73e824c3de088c671d9e71cf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.63-beta.0.tgz","fileCount":434,"unpackedSize":922815,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdHE4UCRA9TVsSAnZWagAAqVMQAIELotO4vw7MeyaKujm3\n2Ax4NBoA7x4vYfjIGx9KkZUuGJTyQm+NAkKB7pdHyC5SJw0Md8Neu1btZpxA\nJMjb7LIWzSgucCfoT+klIL6IhlQzRngPCSCVTq5kN7L/xLd8LLANSe/xVEh6\nw4rz8K/Uy5khvzkKKbs4/8wxHyJvHMcaxKdp/m4iWZdWCEC3dJt6SVd167pK\nu/9yoea5y92gU0M6xXLu8NvHThf/PSSI8KYxatjWlO53jfbzPVgIXT1Ut/er\ndvSHbdWZa4mVyg/RBaLgiG0O9VFuwste3w3lEF76zdgXd8q9EvI2JsT433ki\nuMoLJ1ADbmNRj/QIwMsdq6KJiqBssobV6R7UTRqRVfr3g2izJt9FIa1+OXHd\na/ln+QipbboUQyfAl8XvpQ939RdYo9cASozEor68ExqrGBWIfbSTyTgLMfes\nKIULLzuxiQ3+g3lhd92JkRXVdGpRksqw4V6MZd5E87iLUyx4YzNZCA4Qn6HO\n5HYcOK8hhqDtytvgeqg3Rndj1JmRWPxx0n7POU7icnK9k2i9zBJLvBOOx2IM\nhyWcKG34S8jYFZTtGjrHXCqkGXkg2xRGP2ry5S9zVJvirE6y54TiDMp9AbLr\nz1SfAPmEjIimT7Z9lJPkruNFq3+WR7lxSd2DjxHTorzLGky1aIRJW4C7pAkd\nB0hK\r\n=fH5G\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC5xXJ7iugDWZfy3w1tnOtV3GgbmSCe+4QZ5JbXd6oNugIgH+m+fmZ5ysBVLqG8I/jHxaF/a0bWHFqIkEne+Ecbmuk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.63-beta.0_1562136083470_0.46491678447478013"},"_hasShrinkwrap":false},"0.12.63-beta.1-consumerid":{"name":"teambition-sdk","version":"0.12.63-beta.1-consumerid","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.63-beta.1-consumerid","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-1idiYxhOXLGBtgiX6D41cteYn7IDCJnkXRajzMzBjcoo5nfJShuEuOxGU+kCQ89msKEsywu/lQeo92/3Eoi2DQ==","shasum":"c73e4246bd3e4f88796d4e154f02364073cdbe93","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.63-beta.1-consumerid.tgz","fileCount":434,"unpackedSize":923324,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdHahWCRA9TVsSAnZWagAAsdQQAJPD1AdZxpTDUArHryf+\nxSympfeMm3N3fT9FxMYRThCnGFMsccxH2wqBfjvE3Urn8iJ38ciENrOiUtRl\nd/GjsQw6rwfILDYQJRmOgX8mRhcDfDcfTkNnZQdYXkW19M2hXwWzYqDNcIYO\n2azJp7aNymdbbbjcI0Q0QiBpn9J6PTYa3Mxv3WsDx3/79rEd8zn7x8P0Dn0m\ngdpau2V7ncFyX7MNJX4BMwEUfGnQRYXrvsJIha3MX1OhBCnVD6RpHzIzGWlQ\nJe0JZ25ShW0W2e95P3WEOuaplv3ekq+kVFRbUp0j8lkOey5CGA6/PUQ+7YAX\noDzw6+1hXBZUJ0/P3tqqPlSrR1JzRuS5o+APjb3V3wjWbjNvDB9V4vXAmvt1\nCezELQpzc+sE+Yf8+fdLs6G4d8OldjPW2t7J9aSSFed2pScc0xUrGB+9PZsJ\nDghtAcypZ9iklTfEl1Ml0bT97C8yidmKUZXQ45U41thldTP5LH+YsYNU1wcm\nbnoaHFeTMwsB1qPlhM4WspjSUQcFeCLept5R7XTb3szByn6jmE7Rxw5JUu1/\nkLpYTjePppNtp3E8d0TjAs+TV54xRVELi1taxeBOl5P/Kdyhj8pA8AlTgNuy\n/Kt1FpLIdiQJS3rjdoPsIUjDmdh38RA+Pd3O/2yJOXCCQK6pZVEM/mu+Q9YP\n30Xr\r\n=+N7m\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAy5/2i7Vgfc6czqZ6bZaR3hc1Q+i/+Qz/Br+bxhiJmJAiAyn2BBQM5C3afNjoLFqa+0ZTRURjObFbpZeHcyNCAkCg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.63-beta.1-consumerid_1562224725295_0.26989720570497755"},"_hasShrinkwrap":false},"0.12.63":{"name":"teambition-sdk","version":"0.12.63","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.63","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-7t4q4MheOLEUqMVvIPbMKGA+Vr4mfelcR8izElCphq6CC5LeqiyxMURDkOF5Ye01/plFNCkeCTFCHeD/uuf3OA==","shasum":"1f01406e7317c8daf7f194cbf81a18c60d2fd2af","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.63.tgz","fileCount":434,"unpackedSize":922808,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdJCphCRA9TVsSAnZWagAAbD4P+gMs4serBA0BsQhdVeKG\n4z+0OYA1E8v+US043gY8Lz7gM33oor46HS8qRljmP3L7o7p7rMQvQG8r4JxA\nX4xtLluFOFAf8CCODqnD5UJu7ZRAcNZJKQZVfYLxkNI2A7m1kpeEV2YFrCl+\nbQi/NmC24/IAMkpke2D6fyVm67ua84nz/y38zQyztBibJn9qKFeiZ76XW88f\n1YJOtS65cIDX5w+Y/M778XtLscve7imlmr+gytVnMWNPRRojhCKBR5RO7teW\nS0Jng8I9WOO74HzopZxI+mA7ZtvbmhkKa7uujNcS3a50rM4EoRUcS5sAFCN2\nZ0RNSgwnvRX7lhHlZAlLsXysTTxF3aUBNChfg31clwtn8JjabsqiPvPGKTZY\nt8LHTGk1kL2cZYuk2IlX1/taq77mnvz7AofZrUuR1VrICdO1A4tX5wrId2OF\nxQEkcwDtJpaA5npjarx/Gt36S4NP7auUdmwsDPXNVtLEDl1iUMGuBcqst05V\n8gQtJMqlor4vLHXwC0WKr0zRMpCermLJMzGnc51j3VEVILPerHbOLYuHWf0J\noEItFV+IcZwyevtNL1q4pvSTqL3D1Tqq9IR+Raug3n841V3xsmt5GZHmufk7\n+lB0trfANhZntefxCa6tUePSZ9ZOmlbUN2seX4VFMMIAefYIa6fRZYWZLIcg\ntI2F\r\n=YkaZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCCI3mOSQCDyH6fZNGTQfX7aTGzVnce4ZhE0GF4tH69NwIhAP7b1ukadsWxoEf1EW81DscZPNMAmpXxQeTxWiSaCMCa"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.63_1562651232354_0.0767719167209644"},"_hasShrinkwrap":false},"0.12.64-alpha.0-ievent":{"name":"teambition-sdk","version":"0.12.64-alpha.0-ievent","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-alpha.0-ievent","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-os/M+PAEviMkbg6HH63nUpxmKzceno1JTCYPwUZKnlJbq9VWuGtgqkdzGegbm2JvseEeYtTdeWfG30uP5QPxvw==","shasum":"9a0fda4b5b2e7e8f1cf88ffec9790d1e977d392f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-alpha.0-ievent.tgz","fileCount":434,"unpackedSize":923161,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdJCrYCRA9TVsSAnZWagAAvlkP/1RJZ+SoQhptS/VYbRiH\nXtcy1T0H8OZ1mDY8gAE6f7IfoX0El5fWjmapWv3YwJR7wL/eoUEn80xa02hw\ne+VVGSZOxoT53169abzA07zjOnpz17FfmOuJlJAnYh3RCcK18hKw/vSej/9b\nlwirfjHRWDwkd8fIcQT91jcF8BG9KtwOYPi7UTDfXk+jTNDQo8SvmPqaK4Ck\nPbpO0xGSDJbLqTCsaZm3kLP8vJwxccIFyQQnTPwiwCGdp0te+A5DjvFh+XL1\n1l87MWZgP030Uss75CfwPQgDet7E6kZDcw0KK1HZdWzEOTLaggYOC4xDXUt+\nn0CyMMc5E+qRxScc1qyfrYgxZQeWDMH8Lorv0Pk5jBCXT925DEiTWWQ7EZAj\n7Wm5iWt6Swa6pdFRC8SqihQMKb7fchMP9z8BEc8ExhDNeOl0aLMuspDNOTko\nX00JwyRQMu4yx5Ok35vaNNZuNVFRCR/WWpFWRuU0M5MyO4T6ycj0x3BJnnZE\nOP3ukk4UB8Mg9l7B4jIDL95M++1LL8yXSkYEXVomPm+bl/Nv5+Xe/Zwo+DZc\nBs9VBQs5Fka5VWO3cfYprnjRySaTEP4aWvgDVVAFFByf/vw32yeysdA17eRx\n1hIwElsyZT5LBPAF9vVrEt52pXQpK5JUGbwTExRFUl0VI+jojrTcNM00gnYc\ndbU6\r\n=xnvd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC+nUeq4XSPu9LD5/KqdHdK/g+Y7JuzfCkf8OSCtJ3PHgIhAJUXqkW+7vZjIiJnYk3+MRf4UMKCUWew89pkyGKQ7Sf8"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-alpha.0-ievent_1562651352121_0.24568945235366413"},"_hasShrinkwrap":false},"0.12.64-alpha.1-smartgroup":{"name":"teambition-sdk","version":"0.12.64-alpha.1-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-alpha.1-smartgroup","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-vubJFVLyIBWCD9lnxJEcJJx8K7/2MK/BAx87g8wNTylJ6D1Wz/iw3yA028tTtRqgmkUE7XHnHlTQY0m16D/dIg==","shasum":"3e4a53a5bc2838d4accc9386d7a79971239c6697","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-alpha.1-smartgroup.tgz","fileCount":434,"unpackedSize":922807,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdJZJWCRA9TVsSAnZWagAAFWIP/ApMPZ7iu3AU2ntnbLdZ\nX/lUfxoUWPUpZla5Fdt5zSjeIyOOiKTtFdrh0ZjDevzMh1UteRFnDt5bpuVv\nFuQB9zwMO0BdLpZenO3a45kFCAoVOiCzn2W1p3QaYL+N3JKZpMEdtJ/chaXW\nrVcjnRbGsQktP42VbJy03H+Fu2IcjcsTqPQ1oeoSieyyC8o8al2rGkJrc0cJ\nD9Sx37rkvPFI7fbqDvZ5qydG7CKoYF87ATpnGZf3NO9LbA7dg+HJK2qqWorv\n0HqlYZd6Kl8yf2gahmHZISo74Y097U8GU5lK50Q6ElHT2rJUzUr8BGmrS5YP\nndwwDLzAr5Pot8cxTgd+c4Sn+HGQQqHFtuPHdPoHx0ZyWMO5Wb1cVAeVbHJr\nQ8CJ3I8DGpRY1jSNI6KcA0KE6mmhPX86riBlKYGSADUBmzgA8nBcKG+SkMmE\nvtswA/cK4nOW8lQgapz56Y0hlH7Os5jBkr8eiAOsGwopdhyWOYiuSs0L4n2G\nURcALLkFSV286KQH0IPsLT7RcnGh7M1JR3BNSz2Rn1qxJCyobcBywdBBxQgr\naDuWU0OJxkxOvhkciSUwu6HdO3MgDZURCH51Ct2Ci0yxZoeYddFtomBgrKkD\nQhekbjS452nfreL+5wsjsm6x1zRq3XO+zUM3aSd4MxBYUVuNjbTYE1B22PGJ\nwaa/\r\n=3sEi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAf3+87dWQgli0Kt8dVJuVqhhl67TPiWSY/5JPl+kUu/AiAeVdgEwcSgBkUfACodfaXPQBZn307mLtlvAXOweuI/hg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-alpha.1-smartgroup_1562743381926_0.13677039606223085"},"_hasShrinkwrap":false},"0.12.64-alpha.2-sfe":{"name":"teambition-sdk","version":"0.12.64-alpha.2-sfe","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-alpha.2-sfe","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-jBVW9cszr0+eTw7SMSkWLL+z01upAGv53tmM5FnheduihGBOzOPJxM0TDGnEUGWog5+QezpBzPNc5+Raus+NYw==","shasum":"fda7f599a1dc9d9268fdc6da6e08260adcb0fb37","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-alpha.2-sfe.tgz","fileCount":437,"unpackedSize":924950,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdJZPOCRA9TVsSAnZWagAAfmsP+wSYiYaNCbTfG/pHajln\nK+i4bX4EQUdh1znL5sfpUszQAT7nfyXcaaE6hSwim7UCoO3d0+yL6d+XFtil\ntvf1M/TiTmSWPTyqyJyys0BvCMEJ7G6VmN32xcCvNmYBO+i7qTb+E+UYClyB\ntuPSMrJhgTh2+Tyc0CSR4WFmjR68Qfl0tyd1B3Cfjj6hn3iIlhPPe/wxPqFo\n1SxAqIy7HyGkeNYGPPU9hQjH3lMXAoCHhxkkYEPeuveXTxwfafwMUacK+AHd\nUkqPsdoJM/i8tMrG6FAwlTXhLXy479Xg8S90jDUVWjh8K48zBmARdW8S+WWe\neelFT2ULT1+qbwgm034Z25kz2Q6y9ZPO2wImCAQFRsOMz4vJl1Xga74rQ9dc\nMnfnCebFlTRF+cUO8pBz6Pr3NC65Jpz7PcD24Iova7DSGkIVDi7me0d4rGbi\njro/feWg33DGTCXV2T5LaX4kVFPWShvnHVI92bUCtbBIzmHfEtUDX+HkJovN\nNmpvclNEL+/d+aZxJnxZNnGsVzD7Tn17c70uKWK3fY812Of1yeKC7QzhrQ5m\n1nErzlZxxRb/obtnEoZ7tUuEjWMgLLEgaeEGfae5zsoGSzIHy++OrdzwaO0H\nR5m2x6CgTzoODPwoRZFNUVIK2GD/UGWuj0JnrH80Sm6jYrevfwEe88mcZOxY\n//0K\r\n=EZuK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCLsch1J45yAvvwk2xZZ/yEk+9qB2YQxkCdZPJyBpx3YwIhAOb4MRfT73msld1T3k2mCJHgM5NBGVePbx734udRKfII"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-alpha.2-sfe_1562743757596_0.25321735222823816"},"_hasShrinkwrap":false},"0.12.64-alpha.3-sfe":{"name":"teambition-sdk","version":"0.12.64-alpha.3-sfe","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-alpha.3-sfe","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-BWo8squE0CFoV8oWOW3ypQlLWaqnoWMQppxLKiyQIVy3cPQ+5Y9H/fskNwGCTsGu0Sb7HmH1gJ5nsheYP2PlIQ==","shasum":"321ea349cae709713084d9bf2a4724b7e6712e36","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-alpha.3-sfe.tgz","fileCount":437,"unpackedSize":925058,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdJZXSCRA9TVsSAnZWagAAg4wQAJlct/lLWpgb4JRYSojZ\nuN12Eg6B+4A22o2qXhcBqNue2HINxdYvY6lnoxrqK5KBd6Gy44ghExXddGrC\nZ5xlWpaGkCzLhRq8JdxEZQnnE7NIiOIZNxuN5cCoCsMCYn3JezjdibP1lXYJ\nsP9H7/CzUMEGA9HYOAUQKktfgoTkQzasIuj1BBw82HhD2UH5GJh16h0VYqDC\nUc/iCNVkXiafbxQxBo5UAYbrAIxfzKeFhlATPeEuvl49hkpWxGj31QWrO3xQ\nBmUJVyCuwIVKZ17KF4DoqVrfD9Hu9OWWuVKd9Dp4UiXkce6BmcQbuCArQUti\nu+lqZqdbhOM/t83qhe8enP6JbbKh/0jzYXxKSxHnCiB6KLhfSDrl8curd/de\ng2nkh3FyapRL9KlJxgzSRqf5ZQaLXMJ9dy2m24tdJ7ic82FFVwk+kT3oSr6c\nGqdyFdlXjmrGI8ngW5Dd2QCdGXkq/5WhOG+ZtiQk4KnhsoCZh8TPA4lQBBGF\nhitFp0b8gaC/ifO6/Fu3PKNqKAkZJ1+xQ8igRJbHa9kVrjddXLTaW+BefcXU\nlQhYaVguVmsw7XqkxSkwufRkX7I+V1Wq4k7wQttb7RZgdzX+ykbbzS4AVJH/\nFUt728B6Br0G2euX2NA1po48j2DqlkBOlQXZOs21fGY+YLqJXjd+Jhq+hWGa\n46Q3\r\n=tZST\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFUAcnB4eQEg8jakDXiEnPImgubMzNSRLhs4Px3fZLVQAiEAw7XqXeUhfS/ZAQjHxYqMXTHXDDOCSUEZ6hxL6wlnzKo="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-alpha.3-sfe_1562744273906_0.7135116265660577"},"_hasShrinkwrap":false},"0.12.50-alpha.9-sfcf":{"name":"teambition-sdk","version":"0.12.50-alpha.9-sfcf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.50-alpha.9-sfcf","_nodeVersion":"8.15.1","_npmVersion":"6.9.0","dist":{"integrity":"sha512-tT9nEL6xFs8dKnGijSeJNJeuf8zFrHfxAMS+TARCfdauwsFIqH7N/7azMdN0fqMawzH2oE0//H5X1hAydOd0Uw==","shasum":"59fcc4d032cbac2c96d3a111d245c5b03328b5ee","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.50-alpha.9-sfcf.tgz","fileCount":425,"unpackedSize":897768,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdKDM1CRA9TVsSAnZWagAAgDQP/1H5FIomG0qZ+TRAjKzl\npPzIZMlZVYv95PCIYXroWpKYdyP5magM2rGdMU68JnUI7FxeDtYNM1J5+P7r\ndKWfJkxPbG0rDtUF1ElTBzGf5/n0PnX6hiR072SfQnIsdlWR7LpgFG/s/bN1\nY9Y9tTCbIV629+9CMaLy6STvfGTI2AyxEOQhuKOTkpUnivNujZcOw3DNXEiw\n9+WoPP4cYYWljLeP6NwGPPU5RwxevymelHNHwa5b/6nmsaSsxXchM/fiov2x\no3386r+2G32CqGwnWqGwFA9BmzV1615bj4Dl18+5RULv4di3f+dtzxc1TRrk\nc088bYV5wsxGvqpS0RWf6WZqk0pHJ6sQcAwiCp+1m2W2S+frirMG1oZUsi8V\nF1oInY20FhGcdMJCf7i7czu5sk8HtEnxLTQ9Vf3EdPbmku5UH6q8eYob5Y5b\ndCDuEAcijMNZvUCuP/PXzInglrRyX6FrVAhvYGlLLdeFSR6WyPH7rjHJBeJE\nHrPeQridIqiNx1Kr2QLy2rSxAPAXncQPPe10VrB6rmp6p6o9qFVQX0CTDnFb\nLFdOchfsW3zI/067hMDS4+hlK6IT9bHsNvfh66Zoc1rDu+rE80OMVj+YbNgt\nDMYlolrKlZ3OCnoeeXJCV1shiZhP0aR4AIsvDdH6EIkkeczUXsDMLgH/2/zX\nblIr\r\n=SgYl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDmt1o1+Vq3jMn1KdaZSESjULhsMZpU7G2AXCaU4yrkqQIgFQUcIlCn3U4VqlhdJMwevGhDhVzByxBmQpTGq2OZmgU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.50-alpha.9-sfcf_1562915636523_0.11406601928145288"},"_hasShrinkwrap":false},"0.12.64-alpha.4-bulkaddscenariofields":{"name":"teambition-sdk","version":"0.12.64-alpha.4-bulkaddscenariofields","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-alpha.4-bulkaddscenariofields","_nodeVersion":"8.15.1","_npmVersion":"6.9.0","dist":{"integrity":"sha512-4SM2kw4k+5eObaiYcIbRkQgzWTttuIyPMZH7YnMgJN6stryXuJCmyt9pHb4FdsKPnMLmDQMJczF78qZGryHyAg==","shasum":"c0b8f66f15945e3e737dda956b3b6529fbd4f01f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-alpha.4-bulkaddscenariofields.tgz","fileCount":434,"unpackedSize":923724,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdKGZjCRA9TVsSAnZWagAAij4P/1yREVUISIJcfVulGAzb\nfKyl/skzzsBYLsEinzMsrc7hBbYdzHS+km6POesEoEp4GFgwkYylNA4lIQeI\nDV4dIotrdOqiDTT6ZkoM3/ojSr/X67fZF+3pV2BnfGMsMLEY2BIUEaWdE8ut\nCCt0pH0P4F/xw4/apxOEFAkAW2ZebueHMO1gbjvSTBj1nbit+ilJQ5d88CcN\ntOUnRhpYGkSHvtplwQgmZ6HLlv1MoxyyDv/R0H/ppzl361BVnhJvbx/wbKWd\nW2L/zjV1QYxid4GZwIWxIXeANLytVugLXIsmBIPSzYwIzaxaduk5oAj8Q9OK\nm2TJWRKdlMiXiT2Kft4natDEr/H1K27HrA/JbwHopwlYnZxuaQ82kT9MmsQd\nPHYC7BBnqRx08NmmgF81+04dK8K2VK1J2mrEwshfTAtFwkyi0tE4NB0fNZVK\n5qic2ERb0+1lkgSW437AplJ1AIMZwz060Jufc1c5ibqVGpXCyC1k2Nf6eOeA\nuAatSd/Qt5zm/647z+DLeeymL2T3BGW37QOX8q8iKL/jhi4GEIgjxj0Kyy8L\n1Jj/V6DqeB6m4AA1v+r1M+HZJEdZw+PX5uYCPZyNoDWuSqU3oigjzbZNUf7s\nNpTH9EZ9gtfDmS7YA+c8acElh0IdVl1IdmvfaNQnJNlCaXFSC9XxLC1E0W3Q\nGuKK\r\n=qTYn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID8IlUoBog8pMTrzIMmSXAN+xGtbLojLGXNlnEb1oxi+AiA8k1Rl1HlWbhRYN7iDIjRHG4PYzLk/QOYXxLqvP5vr4g=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-alpha.4-bulkaddscenariofields_1562928738933_0.17570967742027999"},"_hasShrinkwrap":false},"0.12.64-alpha.5-ievent":{"name":"teambition-sdk","version":"0.12.64-alpha.5-ievent","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-alpha.5-ievent","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-j7MfctDnTWHaynLFotijbD09yCdoIUzV8HeNYs6kn0rxxypzCw9Gix1oivF4wqCcUlVkajBqy9fnFcJcB45Jsw==","shasum":"590fd01288055ae2ab6fcd66a49b7d24d51104ef","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-alpha.5-ievent.tgz","fileCount":434,"unpackedSize":923659,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLCoNCRA9TVsSAnZWagAAJhIP/0Ssmp5B+rP3b0coKlzB\n6hZItp9oQQ2Pi+EuuABZpxLNZ3aOovTJRpXoihRFINthBWQHd4iK0AJqFQXr\n0Z63nlvUONvXe4z7VTyVwojgwU5qOTf+fofSDcJPT0DtG2w2RJ5ym2nWTz4w\nEVL5Oo2HMW7+Lq0CKwaILP9nVmn8TvKNg3pKiAqj8k1Kg0f+5fMxEwodnECd\nhDaWUMqj7e7V1clI7Q6din3TrGn1JYfZ0CILAvIC3Hj7K1ZZr+3QH72kvkII\nqvXvJbNUTUnH27t0POl549A7hjWccBQDEiIZRGdeGtNYJlfaG1cwBJQAn0jc\n8sxwaGkeeXulf9GhVivU6mJfk4dyEv6Js+g1918zvgu81YUZ1H/2C5BRzovm\nePH8eV8ifVzrauxDwd08/9eLxNHgzMtC+ixteNnaUGLVOdEbVS6NSikPt5qd\nguOqVTqSQpIe/k4MNwRDn7F3SfOfS+z99oXWDUBwGnuWJKglb6agZoDWnUj/\nHRy+Jrajc+cK/zMvpGFFYQWZOFVAbBjMplAs1jmpM1w3Yi0hfN41SBpzFKZz\nKQm6M6bpLmOrk1HW6d4bMklC9rOxXq4DTsKbYtCzbTm2VBb1Ir0rVMqTc23/\nvaO01bQ0Sroyv/+thV11KAlo3qRXldMvtEMcJ2Vm0AXiX4NTs+nhNuu2qk9Z\njOn8\r\n=voWm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFwFQP6Qkhl8deuqOXx6uDrXBXjj3hJo427USsJMTIq8AiEA6XkJs6OUMBh7GUvC/rjoaRAcbUQnuVCVlxP2dOreOXQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-alpha.5-ievent_1563175436433_0.9229334093688066"},"_hasShrinkwrap":false},"0.12.64-alpha.6-sfe":{"name":"teambition-sdk","version":"0.12.64-alpha.6-sfe","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-alpha.6-sfe","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-VNdsb145Pw6zqIEMjIwUUBDu6SfPE7kGvSGlv0yVYjJIu70/PfEdEc7seGsyHpGqibbF/YAICV6R2QoVBtIcaw==","shasum":"7ffb736051cdcee03320a23cb1a7846c19bac784","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-alpha.6-sfe.tgz","fileCount":437,"unpackedSize":925985,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLdXVCRA9TVsSAnZWagAAns0P/R+31BtfK3YdbZEgLkEk\ny392EMLWrucwLr/9jo6ItaTHRr8EJyWr6Avd2HmxMn40mlAhZtSBnSOxjN1X\n8OH8JtRT5jKNT2thshzvAONLDpkVECXda94zuG7bAVjPoGt1zaSzI4u2IPvP\n3xGRAEV0nkUbjwN2iRYtW0HS5l3XL+VKUQKiQYdEtk0N/m0ZWvLWEmF+pHOI\nqvnENMLZEctgnAIBRHnb3DG+xwFpfz8DP3eobq9quzzV5O/qUeYM0zxgPeSH\nQgRB5IKBUNr/RWTd2S9Ni5+93bYKY8+5icJ1dlAxQrkpwIKZq1CtoXexkXnk\n32N1p6IozZdzx3aWdZ8C8/dMvEhxcTIaGAioR+re21qAvfipjtbYSjbB78UF\nowhuxQY8mvgzZwaqCMAe+E5JWNd/Zx4uKIwlY80Y8VrTCDJOvsVpy8kTwKkK\nERIFUjzFo+ArGNxo+o/bHm14CZykltl72tQ6oQWXbY6ohFMqbdPKGxFDTFE/\nnb0Bhbhxu7MAFbiXZ1Emsv/GhsiuIdR9yRmXawsiAglJiPj+6lWzQurQG3HX\ntQ6AFIy1WPqooBytMDmBmmWVQh1LwGXN6HPdimjD3Vbk/dcELxVb4KPcRiDG\nLZKzm7XlNOEQ9ufY2x+Jl79Gz4iESU9Ks8s7RtLo/KC1Hd2qzZyW54NLRxte\nzwNT\r\n=twFH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDEhPuo2CK8bbHUNWOT1n+V9fsnKFtdPtSzbDYHgdvMhQIgSCNRZVtO8lNW4eGNn+0rKKewtR90RTZvZvRxRPh2Dak="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-alpha.6-sfe_1563284948445_0.13290109329330058"},"_hasShrinkwrap":false},"0.12.64-alpha.7-pstatusname":{"name":"teambition-sdk","version":"0.12.64-alpha.7-pstatusname","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-alpha.7-pstatusname","_npmVersion":"6.4.1","_nodeVersion":"8.16.0","_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"dist":{"integrity":"sha512-n2TOEZrNPgyxGfwhark7ZpfkBp2ihFHdFeUD6WMPzEzHk3/1XSvnTwYreaOel2UIcxt67yssj1iE546p9nowGw==","shasum":"af79467f4627bc2e2e26dc89fabee6235b1dce56","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-alpha.7-pstatusname.tgz","fileCount":434,"unpackedSize":922864,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLrXGCRA9TVsSAnZWagAAMboQAIawdyQKWEF6etZnc0sk\nMBYz9Pytn6G4yJg+hJ3oPVNJdk1UF2w42GRdmqLA0V8w9hndeaF2OidQxzHY\nPR6pR08KXUHvAHXIwon28S+2HDorDSRFQ38RnJZnoofj/47yP+D9V9oe/Jz0\ndO97DHPH4fTx1T0rvGJ0v5tlLBsYX+0EjPJBa9HvZm9Wk23k/sIsKkxQOvtC\nO9MGOTG2yYXoM7rumfHhy9legVuAdi2yuiNDaxfHNRuQzsLICa930TLH+yMX\nJ+lauCVvHNfnavWim3J6ESgF4deLBfMDeZGgCnKRF9Jes64s/zZiakgSzkwY\nNOwthOzdGCOYrjD0n/FJZuzj0oeJPRibWu7dUZMjdw9v2krMO4QRm9r3Zs8W\nvkU5ixVjadfyNB3ujdTDEGJyYYa7nlY+Ifl2OnUot0lfYNoTNPOdqQSXzBAz\nO1c14ykeaAb/rDVwPCn9ZbdXoVS9aNhDQ7hAiW6wTgD5ZlYhmI9kfCwQTaCp\nw0/Yn8WFjhbfVMLjqdmZ/hqWkJoeqPLFMevENwkUbFKSi5ZSicrv/EbV2hab\nJArZrOBDMT0cEntPr/sHvZxBilbwrYkTppZW6bSUTBJQCDkEvVAKPyTrlmAJ\ne0BknnqU31LzQ24iKwfRmVxV85x3jHpKKWmtH/uIMmGk0GXuqvobFYuQbVA0\naGLm\r\n=FOC+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA9PGWy/VvM9PLKBOpQPgAnTgjLNNaDOrdAHr97h9gmVAiBXGa+EKoLWeJLELE/hO4CAfNHRTSDH/ss1ZCtGBJk6IQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-alpha.7-pstatusname_1563342278067_0.07246336514681495"},"_hasShrinkwrap":false},"0.12.64-beta.0":{"name":"teambition-sdk","version":"0.12.64-beta.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-beta.0","_nodeVersion":"10.16.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-BqQI03MZ16FnlamT7yE5O4kEnvqNKDaycW0XhchWiu0qYqOHSo3TbadJgK4MYL4WzaJJB6eb23HqxOhi53HmAA==","shasum":"7929fc82a4d8bf35c98d625f3a20bb02e3f0d16a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-beta.0.tgz","fileCount":437,"unpackedSize":927669,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLuhBCRA9TVsSAnZWagAAEoIP/RUYD3ySmSi7aDd+mtGv\nzvtMUwKK/5gZHVgzFx4CAQ0EH/eHp/HT/HcDUd0HtGWFIgQtTAZ7x6SEwrws\nlKRkmJo1qaTKlVSTnAwvxN9sri9S4coOzrXzIiSy8RyVetRMUNW+lawEVbtV\npJ3wq3YsEI7Ad+EXdQ2vsT36tr0vqFGRlihWTmxeXb8qKqKTb9XOxfJawvlC\nF9KTsqWNy/g17tsspYteafnCmCqg60rB6UqNjbElZkg4ZLryBZimtMws3j67\nScuya/vXWEDSVgstoacTER6K2KJfgBLezUm5PD65h0EL3tp/OHupt0MvpQP3\nZMKxPoGzFDGcfjoPRuqAzG7Sf01RRmGC8A06g16tIlsiuRlXHWFvHb6WvtJD\nN9FD2tt4v9XrGhLrLza3Ez/D4bomevbzpAyza0/OMIB6qpNNepZPlVOFGNZI\nmBSQUdvaRH/43F6L3p3TS4/s30ePFTuY1XYiQ3c6/MkBhl3gb7VsvbQuMwOn\nJaU/klVZ3cDPwFszwpsMCnj68dX4qwu8rXt0q3FuuHmWoI7kDP5FaUONVj6F\nBrhh+NXi6lI7B43SfNBYylGq/zHP28XD5OBqsDwjb1koNzmgG5rQu37HBrm6\nL+iVrNNTh1yi19byE71/fS0cewGMkSXQtHlHq0kzh1MBRW4RQONCrsb7i+Tn\nxqO3\r\n=1ksR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCy7PomGJbb6O6k29pAIxg23vzyStESK2tMAO1Ri8pDeAIhAIDFqR1ItZj+ZKQUyY96djyFc6dwix9nX1RdvIOdXYb2"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-beta.0_1563355200772_0.95468709150591"},"_hasShrinkwrap":false},"0.12.64-beta.1":{"name":"teambition-sdk","version":"0.12.64-beta.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-beta.1","_nodeVersion":"10.16.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-WIPclUf9Ig6z4U3zKkLFQaUKX4pI3+LCsM9SUN7TJfXo92ibuacqvaDBILLvKgRVGDioZHeH1k/T33ImaxseNA==","shasum":"321b82f9c1ebf07da43018990a297dc8c7145679","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-beta.1.tgz","fileCount":434,"unpackedSize":925002,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLu14CRA9TVsSAnZWagAAGFMP/AgXuiW9M2R8A5faYA5L\ndoNw8lL67xfiwYsfrBSzFoqxpYKrGDKe7mtdCXTHIqvqsDDsZXhdXjgBMkNq\nA/YD8aIX8ATg8p1VKeHo6EWw1jdRKRnue+UgDh43K6bh4JvHK9jbcnLxrryL\nftQ364dVq6udDlGq1wSFZIkRXXnUbnyelnbC3Y8D0otD8pYUmMK02Wno/Ypu\nt1zmPmMOdD5ryU67Zxu/7GjQjSr+4ScFnAl18Iz26J74dfkdcD4FcuKUy048\nY86LEodR8s1g+ze0sW2fQl26dDXn4XSCM7QZCNOLCUQ+5J/8s03MP4iGLyIk\nYyAVOCutLUwgb2qOEk00SLx8reOj16jcc3z+BW/9yahOPwrz3jqiJmH1LzHD\nQVRmsneK7CzPfa+QbbaRwfi+S5LTCiVwuOPBQeGuNhmwcHHMHdmVbm7lgZa8\nmKw0l8jAgktlYtJ4viCCxgrLGkd6y6igdq5WgHtLAV8rBqnpSPNGloRQ5m0E\n+Io9jliXd+OXyfOxmYvgAaMnTaIyClSYJhwpr6hjHMpEEYe4R1INkBakSUIN\np8VQ60p2mAq7Pnb8zWUSLU08r8E2yqqWCNw0aSpKK7c6ZOugLKdUC2vpUjM8\nBss8jo2bGuweUG+r/rAtuyMy7ekyd1Qexd+nx5Quii6IYiNELbS2Bf3Iurk/\nC+Jg\r\n=AxSr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEn+taThkohupH3PpBA8Tk228e8wE/drJ53rSP3iqRWLAiEAlqbgVX0ny4CNxZkQWuXZKNpsBeCVhfErnIATrmI2vN4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-beta.1_1563356535852_0.6728600646013732"},"_hasShrinkwrap":false},"0.12.64-alpha.8-bulkaddscenariofields":{"name":"teambition-sdk","version":"0.12.64-alpha.8-bulkaddscenariofields","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-alpha.8-bulkaddscenariofields","_nodeVersion":"10.16.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-LxMrK7xU0+8H/IDeQcEsW4tDn4lScbQAow4QzAOwJQyThlpLqgQ/aLz3MdP4KMUUD1lXcxhkjxjit2eqWtxjCw==","shasum":"efef6fd077a28aeafd7d136aa373b393f7621abd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-alpha.8-bulkaddscenariofields.tgz","fileCount":434,"unpackedSize":923704,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLvDrCRA9TVsSAnZWagAAJSkP/A10oaS6zoZE4dNxdCj0\nf0nRvZMUqUXKp+s0DJ8UmvdY0B+WRmopxb/B3VyMqKxySrXunjnR1tAGPQ9G\nQy7mywkXqKx7eCoVnvN7OgILpI6AlLobsjh5zjayO0drJcWrLl+pJ5b+0AaA\n4Cm0cgpp50uNo0pBKsG/MmDy+zvVrjDV9sDgWCmJak1+e1dRJNs5Aole6mKq\nQJxmelZgPWEC1GKHSEcL7k/KPbqXBJR5oGZoFea3tVXo9Y+r3qWZqD68KLvr\nvuMy5GSJnaBh8DRZpV3/tpOOtPhqwKgx1mJU5vP/3NuXTu7oBYCgyu54pU/H\nyg2Oy2LmneApa5b/6BygaOGZpqP1YTNdUEfAJaPnbiy/CcrV0aXCoq/rkcDA\nmPKtLDzZgFtwWKhtoi2JyWfUElHkYq5h5beCCaJSZ261eL2svyY2T7dLixQt\nyMA44AlegLhQcgc1RBwdXzmBTPJSzYvkpwpjlyudnIqfCLTISd90ZMi/5Ka2\nzD9Rg0mtkbpcULh0Kb4+7GJo1up10YwpRsaXoWtIaQBp6M9wVIrh55QiqPPy\nto5vo9BhFH31Vk8qi2pViQwt9F766VBcdGXqvcwBMqjOBTega7qtgqbAKqaS\nYcbned/VqrIw2z7ljBkZ2CogEM8aoNwKGYm5K0fl6dReZtQmcc3HfFYgbrlQ\nfEZ9\r\n=PEXs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5ZdbrU77ziYh61EK7X7Z0vPuvIw/V1s6pdTjFdZuZjAIhAKFi6Q4tvvFJT0LIEdqXx0oHx7CMkIC5oZfkWCjJAjkW"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-alpha.8-bulkaddscenariofields_1563357418324_0.20028128839406967"},"_hasShrinkwrap":false},"0.12.64-alpha.9-pstatusname":{"name":"teambition-sdk","version":"0.12.64-alpha.9-pstatusname","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-alpha.9-pstatusname","_nodeVersion":"10.16.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-mPLqofMS1uXBTRPNBc6T4FXrIHxiGDbvaCWBbWed+NmKQ4bLS2jWkBbVTfYSYSB98NRxepvqi9vqIp11EcJTcA==","shasum":"ffeeee5e5db2d0c05a5c44e498318b41c0768f97","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-alpha.9-pstatusname.tgz","fileCount":434,"unpackedSize":923730,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLvRjCRA9TVsSAnZWagAAl7sP/3+7PXgntNNC395pMCuo\n8QFel8XpyDNftNzFlc5NSyyKZvz/TMRmIMEZpfvGhuX3Sygl8fQEhUkLrBuG\n3nxehSqSdr8IbgnhxoI449Tkbq+MGQNTZrvl9TBKO9YgmlqR06v5viq7JV4Y\ncKHRCgfJx4WLCXzCTJZs+mLlAeNu8s/uW5Y8eytym5+3HTnw1Qu+4EaTn78P\nZsN6nYjiz0xb5/3PTiinRyRw0L1mzVCDAUByPr0uGPuedyHVYn9ZRDaifMi8\n+KkEgEIMGq2s/wU0TbIjy5lfXa3VszzsQl1KyM5i7B2pIHLhoIKCd0oSr21w\nnYjm3B/7Zz7loOsolaqCSDfEAQ7vZFZhjH4WGGdj4ShWcMBqHMgtB/Y/QZMK\n+naa3pTo3Q/4tPVLBsF+UrFEmbAHAH7ercUC54uvEzCq5j8ddbqKSMIVSceN\nqJAaMq1gD+o5u7knZ+DTvzS38TTk/bgMpzRBORCeWLeRx0B9ePEySSo9wlOq\nT5NAXlY6cnEFkVwRMfwLwN8IOXkM6FKWYkNjJ7u52p/iHclcEez2NIeE9L7K\ncQyaF0BYbL5372Y2bspfoYMjqyxz7ddez8TJy/eZaWIE6khyFDPwca4L7G9T\n0zaQyqHDN0IJafdf2C01KDtjlLMvRdQ4oDb94avnyRug8gh0YW1Y3WZ248Yz\n158R\r\n=/cac\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC9waL+Cbj3MEiykDN5ce71/xuTP0iXZNGE/b+hZGcoxgIgWcRWS/Q0u/8ofNoagsAHRzA6KBYO4nsdlUhyISfqxsQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-alpha.9-pstatusname_1563358307234_0.43883375164149196"},"_hasShrinkwrap":false},"0.12.64-alpha.10-ievent":{"name":"teambition-sdk","version":"0.12.64-alpha.10-ievent","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-alpha.10-ievent","_nodeVersion":"10.16.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-GFpgjPktokA2u6Uz6MMTv2KF6Tl7P+KJA3dQyBXA58CQ8mC3nbi1fZWiHay3sw3BW1sK51V0eb9qnneE7tsfJQ==","shasum":"de35a4b3a7abd912f0d3d907cc41e7f66fae74b7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-alpha.10-ievent.tgz","fileCount":434,"unpackedSize":924513,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLvXYCRA9TVsSAnZWagAA5kwP/0xLxMNPZJuaYkN4p1Hu\ntLufelcfwPbJfHVHqgLM3CurZDvXE9J7t5McfCw2ScB+D9g7v/Kl8hjlWFyR\nyvND+kOgRIBmtyaHnZ0qXA8OOxJFqhihnoYuWZ37Up/Ag745r9f8jKVvgAkR\nQA4UdsL0OwwRdQEvJBPS9lO0aio25iIf4zV8uHUIA+3Pa34GnKtPBgJOZ5Tp\nMMNZQmNtAwJYmwQBF/MC592szBudBrN88Ip6iTa/x8M1QMllWkScWKSIoZnW\n4uAMIV42aFnYEUjNHe6niemuJcgWAQr3lPeCCxV4vfetQErfFvFzXXzB3iBG\n9sCfB53lNVAJt6W3NVgvD1SrM/wS10rDzr3CdBC43eXWDtNvRWtp86bIGS4q\nv60X929CTKrRItdI5UnC7Wxn6uHmPuurIlhs9kefPCTzZjzD8GwwiI4NtGA3\n1UOhQxgkeXicz37OlZPZX+oOYjZO5hF9Mjj8h3/8NUtybUCOwMInSZZAVMAm\nUvkCwuyshp+NbLm9h/VsM2u7chhtj4qLFRahjVts7kXTkfrxM/OXRFqDIBjk\nkzWQyogRgxiBoq1qrEn0+1wv4yG4MBTkqmsF+MrErMJ0WgjwGsB21NSvNtmZ\nXQVA+qkFVnSSCY+rwDNLEVq545WvcllhYwn1rphdfeRI3yTgvcPTfSVq0QZu\n17N0\r\n=CzSp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD6Ic4b/Q5Q+CSVhC2p0L7yHB3Q3TBv4TQZWOthGw+cKAIgCIaVKANa+Q3Qzoe4i9Tn83Kt327zoY9PDVHsrh6KYdo="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-alpha.10-ievent_1563358679846_0.553581249625819"},"_hasShrinkwrap":false},"0.12.64-beta.2":{"name":"teambition-sdk","version":"0.12.64-beta.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-beta.2","_nodeVersion":"10.16.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-1KavEiHRJZKlKJlFvd11wXjyjxykHi3N3j/qsNZD+uUg5zXL3ZouEwecKBPvAd2QfZoFRB+K/aMMKAXYiMRHJQ==","shasum":"4b1b6f0395bfc7eedacf982cb160db7a0fd264c6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-beta.2.tgz","fileCount":434,"unpackedSize":925176,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdMYtDCRA9TVsSAnZWagAAcQwP/jE0mbdwHs091TWU+wFF\nHmw/p3uOKhiG/AmXMjeZr7Z+Jdl9WSdhMFmlSLyQq0rKRIJD8IKTdgftc4Xp\nKZ/JT6WHg7B+3yTwcy01+H0CN9oARTXYCFBmV4Uo4Sob6j4cVpeI9iBs8y/u\nqvkeLwtQt2auBv1HP4pVF/M5HAcsi0GG5ASkRJKgNe8x8o87U8X02lyQJw71\no49otPsqns78/fUsYxsOYSWpO4VwUbUOu8Cw8e6bk2B3MsMEyCOi8C0nrOlx\n8lqqPJ5ES1TjK5WADbKof1wfJz+cm1TSrjxcVtu844FSiXMZWdXG6R+ISREq\nVFRa0OWKhehtZ6dMIAeByruZwlkIQGYFrb5zmGb2EXc1k0oFiw0h/SygEK/6\n02f9QH7adrLgXcaVae3ZHcg9S9IFriU0JCP6CzLLMRpci7agg/nZzcT1QIYJ\npdindqQAtVQZXpCLDIfc7GrzeXk1+LqUxHjTpYnVxHgVCcULRrAyAYpzMwa5\nmk9dZXVyAxhyS0xFNM4G4rd572RoNWopNbQZpm7ONmrJQB1mg0zHohUyp2WN\noYq8DN0DOFvsg2tIJ+Jv9Fe3d1opASFyYdugy10FCJbd45QT2HRq9WsS8+zd\nP/5MytrWbGCYMRGqO6DByEdNQQ6cymGO/QcOZdqu1O21OfuJimCddJi8NuKh\nDu96\r\n=95Xk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHo0HfrV+Q2MpB5SV3BJdIjo4zcF3xCajOcaYuaf+OeJAiBYgS7SvahVQyE4v4LJNyM1ANBSw57HV//l1yDn/gSugQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-beta.2_1563528002276_0.7824862974032383"},"_hasShrinkwrap":false},"0.12.64-alpha.11-pstatusdegree":{"name":"teambition-sdk","version":"0.12.64-alpha.11-pstatusdegree","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.64-alpha.11-pstatusdegree","_nodeVersion":"10.16.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-0HaZ+LAJaPXiS2Glef4pus9KjyFEqz5oDaX3e6fcswHU03d9SPq9BC5O0zRHX8K2Mqw9Gqvm5DReeDAD7w9kUQ==","shasum":"9f66afae8785af27c9295b87e710237b9eaf24f3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64-alpha.11-pstatusdegree.tgz","fileCount":434,"unpackedSize":925634,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdNYEDCRA9TVsSAnZWagAAF+kQAJvPRy4cnq4g11kHtJ7/\nbJE8+qq1BHf841VZKafpB+n1ee7O00PJT7YpA/jgmVWd42Am3U12KKovbe6Y\nLaVISbtNF2H3PVjohypXBN/AUqEwGfXGZiykA3A7xYMlC4CK4Q91pYcebvxc\npaex2upTHSTvzxAQax12quzKpQLruLwXm3Hxqiw7S1NHdxsOOY5WyiPhmN1V\n8Uo7imuyFWZ6GrL6x8zh8OetqaBCmEVnm7kRP7AJ/ZPkJcXAbfRiiQCYbOV2\nt/HWwCYHSZpRQulINlfiWEbDrDYVXyoIjF+EkB/K2AE72QOxk8pD7bBfRUxY\nDy0iR6uIjLCpo+NtLlo/rMURthaWUqtD7GHumLovx8KgDfpO7UEmXrMPG1El\n9xGxTu7t/Eo77xmSDGXxWVMj1p94ID56Dg4IoNW/UbWTSh4bF7/CufM4QDrv\nkwXrDQQKvxBH/voykzU8SVudYcJ0kcKdtZXmbcXs7som7ZfaOzPebk/1pcHw\nU+r77oj6N7laqJpY8ftkoCK4yIuhSxZQmCEQyLYafqCtVDfSMBWunIebUY18\noNimwCWAGJoUeh/HCIchd6HJxfDbzzf0KaNll/4xLEE9z5/rViPsEdy4LQ4t\nUkFo0ix85HIR4jRW03sdf2ZC3vbhc3UpZzz8KCoTC3zPsDb8kHqs9yY9Wwfd\nIbBJ\r\n=yNFc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBk6A9q6Rani5nsXbIFPilWRsDyJLDhHPEPWIxgrLHu3AiEAsRhpqzvxifHQJ6sGTQObzxk2gRbxIt3DMXzarLodTpw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64-alpha.11-pstatusdegree_1563787522778_0.25289835273642014"},"_hasShrinkwrap":false},"0.12.65-alpha.0-sfe":{"name":"teambition-sdk","version":"0.12.65-alpha.0-sfe","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.65-alpha.0-sfe","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-xeHT/1DF31oHJ5EV+LbOFod0BTC7xKGXd/BXs9hP19uFr2+dDwjQnfzgQyyJWMOXNzVfcrjp7tG6LWib2gfFPw==","shasum":"ae48a32a18c9a1559c6ba5c211d652baf86d68a3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.65-alpha.0-sfe.tgz","fileCount":437,"unpackedSize":927848,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdNrI4CRA9TVsSAnZWagAAOCwQAI+iZbF2Ce9MgQ2WlZCT\n/w85VsYlLoKMTmT/V6cvTHSKybqpc9pz7AswUueyWL+uX9jxr38pKrmNxGac\n3kg7O2Ot0dAYV38bLcZCis2CtUA1Ogz37mN/NQ3ZebZRN4d3uCBFNj7GdgQe\nmrFbNUgLZ1fhgfqnDK3ZBy3ummRxERhglh+sE43lUzl4BfMBVunxJW09HrrD\n2mhIM17U3mYF5UZAA/xc2ZK6bCon9oaSaSDTU0u8Rl5RKPH4k9TRTlTrVv/8\nDbtbPIwQ3Sw9KNmkadjA6D6p3xhl7MGEzu18RrsOFDIV7X4IfC+Dqka4sNJL\nYNOskR3LfwzyqtHYTIaeSOP//ziSYJ1DemEOwa3xeqgmWqWCsHaR/7kRILwo\nPmeFoxCiZhOq+IdEpNkO5BoDTu6D5sv8E5bc7Sz1/eAl8cfRo7Tyxyma4lYc\nOlNvRj/58WZNg3qiuXxWcgz44MSRgLNwY3Ii8s1WyAH0D6Ri5QoW4y55YOEX\nWRCcf8kUWVkFqnqBtMDKeNwAO48Ip/wge5R4Tgq14to8uiOhD3lpFW5fMDL2\ngGJDqEx3Eakc+4L1GeL02MBG4woaxBzsCKUIV3eC2cod0Zo3pGL0+8ZMsRWV\nJg/Mdbn/2n/nIM7AlOZZukfzOMMaK0M8YyOAlE5JVTT8nwgp5G+wCKKXadqb\nBGdt\r\n=Qgdr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGM69drZwY5t+H01tg1IEkVJpIso4bxn+JCHpVks2IsmAiA6zbGY1JRO9w0LmuaxXX0ERp7dfF8di+hBXhwux38JZQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.65-alpha.0-sfe_1563865655495_0.2725355864382031"},"_hasShrinkwrap":false},"0.12.64":{"name":"teambition-sdk","version":"0.12.64","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.64","_nodeVersion":"10.16.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-45WHArenf7K3HM7Vxx5vYDtHamjedql3EPPIxGcNomWQxxCRfpBDpOCL0RXI9U3VTA1VMlI2bydCOyUACVm+0w==","shasum":"d3fe3ef24251722d100a066179b1822f3be7a62b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.64.tgz","fileCount":434,"unpackedSize":925611,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdODGPCRA9TVsSAnZWagAA6BMP/i6Ki4KtrXZ5QvPke0Br\ncea8+2sMgLpBfvDNZrUv2WEgzB9CNcW2vCbDWwB449mBEsrc6WPpM+QU1pl9\np17NMhflgKa5uMd0Wd2Ufs8x2rL4MKRnmBEA1ObxVeivJjRTnBLWKN/8W07o\nVHQCUKxHPQQpSdi6hu2i0mcJNdJ/JlBN/xg/seu7njDeN0z+2n29/kh27y5B\nkS3zE5adLOH1yPi12tZ5eBvVjlujT8rCjpxi2kIIiw4XMaAIGzEcLGeDG8lD\nd86/TcUHqbbHxyTgcqZc9HdewWfnYPgW9c5Ein5sjwKmAemKhwqQeSJ8XCTF\nuJ9mlJOzErwx0dfDszDJyudYADjOi3hehuJNnFqdbJRRkHoPidRo7avrmFL8\no/EFSTm+YCCbZs6O7pWtaf/qtX/6kTxXDUerRw0V7oW5+NldsBviq9IGlLMu\ndWIA9w4gXY3rai3VylD5VKo7xjFTlypzL9RNFBthYBMZpNTYr5vxNK9Dt7Vb\nT/oJ+GxN/hmea5tP1cYavQmS+CU+KiJjBC+DP9UtnyVM6MdHAuqssFP3Tl3q\nXAMgV/5qop8zTa4tFx76HJLgVyj7S0ovF/0LyFGOczJsJdkOGf9OuB2Cw9oY\nLBks35um7JEK8ZkjOHdYt7SxL6+L/Jih2eBAosrNY3MyVqG2gxEFDeJoF0mr\nATgQ\r\n=O1xK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGncQKbvlGICAqGAplSQfPtd8nRTUkznAbzQuEu1DkpaAiBSiPS4xlX4G7GkafNeggCAvxC7B8ALQqoTSxl6Dqo7vA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.64_1563963791183_0.9984580178644431"},"_hasShrinkwrap":false},"0.12.65-alpha.1-ptemp":{"name":"teambition-sdk","version":"0.12.65-alpha.1-ptemp","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.65-alpha.1-ptemp","_nodeVersion":"10.16.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-1y3YfRu4BJa2GxB5tJDOZKdcTYMi0VsKQMvjKToY+OMc2fkCAqx9Kjt9W6nqcHKlg5hUkXpPcZw3Y4s4NcjQXw==","shasum":"afa1d5335523f261a9d1015bdec52331ff5ec89c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.65-alpha.1-ptemp.tgz","fileCount":434,"unpackedSize":926105,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdOWQxCRA9TVsSAnZWagAApZsQAI2RFpg0/HiaKgmoRq/B\niu38l0i00gLvsAtoBdfuKUjG0E0e/5yeuqSuVQyjH9kcSZVY3LfTbwnWQCXI\nBv9hKARayAgDHzeOYF369UyknhDvRONsOr+qqLB1fecpjSJMweH1sz6E1vVC\ne0apVH8dzSq6oB/0YZlQQXZK+co8FJb/ukjgyhVyKZmkrvB3Yx3VNpa+b5J7\nCbkEZnkLCH0irnwQMBj99ufgtioNmYSp6VTY1ZhuzpROOozSXG50Yyvhd4GF\nw3ey/PaBazG/aRGS7oxGGJ7oLR/jPXHuT6oo4Ynxlpxlnfux+qM61GTNhP41\nS/ac6ewFc/Ym9qlCpBLV9LvBJJQzY+kSyOKZnxb7t64oPDmDFWnH/UBWB9U5\nfBG4UJN8CGOeJXDwwf3m3sHv6l1jDlkBKiw15vpbo7mG5MCspiX5iOSFigZp\nJd/CJczqEnpdGtBTGcSP4vz1BLGglPYVMux3I7kZMCsx6KZPsqXDwJVbIHvc\nhX0jBJW4xPeSmtAVf289Mtj9NtJMDfPMSmq3TmwgbXbCcrcTP2hRF1eh5an/\nueRB5iFX2IS8UhX9V8Ce3TfJjh8teutNOdelUJAdOOvFAxZ/52J3OmKBh2Q/\nC0KzI2NstGB0FBpo0Z5x2xpZlCVsKuppHN+qaNHO5MOgB5QrCBjCSV3WpjqF\nUeIp\r\n=eSpF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCNMYZoBqhyZmHSdsCTwHGWtONobbaZguKN+EQx4ITksAIgTdccNhYiGaL3U99GTzPaOcR3UJ9FjNBWKm2neoMJGdM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.65-alpha.1-ptemp_1564042288661_0.8323831473514878"},"_hasShrinkwrap":false},"0.12.65-alpha.2-sfe":{"name":"teambition-sdk","version":"0.12.65-alpha.2-sfe","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.65-alpha.2-sfe","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"tb-web","email":"web@teambition.com"},"dist":{"integrity":"sha512-72AP8LbACKbWb80NruT7FotzbbYw+GVM90Rr9jmzYV7BAmtr2Rq9ZBUG2dFw7Z+fznZBMuAxKu2ADyedcE3N2g==","shasum":"54a2529f1eca221e7f6c94d3a3ce50bccddfdfd8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.65-alpha.2-sfe.tgz","fileCount":437,"unpackedSize":928290,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdOYh7CRA9TVsSAnZWagAAPDUP/jeh8/LFovZhstzy8M3g\nMIdqW0Za4lQaxB0GTZKDg/AMYX9MzXTeTkcb1ar6zR01M3sJEdJoDMiSfG3v\nZb50cSulHMNU0vO5msDw7+WwmopQ9eXMKXliiVJUPuyJIoeDAGcX7XnY4f7J\ni39AsD64QYuirDyOfiON0IRiO8+kXudk0bp/WWsq0Ji2E0pSeFp8EuhhI4K8\nQumZJ1iHUW2w4Vb73SPS2LjB4Jfgxn93fdfE9rZwN3D3PHh6WpyHJNvuRx+5\nHlIoxgbb9tOuEGuCFPyFGBgSvPiBsIwP38utBZEaXGBHVRnbLC+Z8jtNBxIR\nO1q+4qXj/7+29UG3Pp1bcVPoHDpIVwMW/Vl6ZsSCvbs2eMvRF6fNgEi1A4XH\nUHB3KbhzmSAYBQ6l9zA1qS9y7XBbHxfIh5IPi9XMQsx7DYnrf87N9pJM+fLm\nvm5/GYHiBf2InLDeF8/9htl7XPlPhzFSmcOLDsJxoDCYswT8yspdHZxjYhqB\nLS2ZUjoYP4y04F1RxhFZbAVydHbgVNpM6bq+wXVDOJDiVFcjjVaTf90KftvS\nvkk63qGi0pPtfAD944Cqy3VytOb43CWlYE3ATQCs6tCklyOgBU1W1o7thDvK\nypuvEwjoWT0AQfIlugjrhy09zV2tA6+/ExKqNTjS2Do25e/gDZkFhqv6Pn0C\nYffh\r\n=ZBa1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEd4l3B2eq9Cz1nfL6JIM9BYqzw8YB8C+EE1Wq9Mo0K5AiAiL04/qbvaVeFvTKxYxAOwaEahqqE0xkpiv++bxxH1Hw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.65-alpha.2-sfe_1564051578278_0.37480134076103644"},"_hasShrinkwrap":false},"0.12.65-alpha.3-smartgroupviewtasklayer":{"name":"teambition-sdk","version":"0.12.65-alpha.3-smartgroupviewtasklayer","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.65-alpha.3-smartgroupviewtasklayer","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-o9PRnsvtNToQtVes+IrgSZhAGxGBMvITVfsH5HaJMHJ8OVhLtDJt/qcdpBYqFJOss3hJ7ZloQqshHD89PJmxlQ==","shasum":"3a9312811c720fc321fc076696316fbd91a07e47","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.65-alpha.3-smartgroupviewtasklayer.tgz","fileCount":434,"unpackedSize":925943,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdOmz5CRA9TVsSAnZWagAANkQQAJB1PC1kEAyRfJXqAi6q\nrhPX2Ct5i8fLdU9oSF8BIRvQBkI5Sg6dTvRT9KS6isW419Hsj00frGgfF1Ix\nC0MHlo4q9YorIPyF+4gQRDfUH8SAzPs4KKYuvFoJK6cJykiZUkm3UuB7Ybud\nxwjXXMXGCK1TQZfvbBUAqXN0vJurkSZSBLmLWRcOwY1KNtyiiuRAVR8cT3uI\n5wM0wAHUGrEsQiMkSeTbDVS6BA2RuOH6/Rl+JIdW9T0MeqI2XODaKG4ZIba8\nYfT4Lef0T7K+ulEKSsvd6Jy77FQ+pIleIiF9B57cRnvH+Sh3mqGjPQM0vGue\njLLwjjFxIylAzGCvIBbUzF0hm6aNqcDyXK+g764sbhf7P42OAT0ojwQmjCf4\nqOLTNziJOfLiNhtQkg4sC6BwIKj67h/zed3N20/KjbLcleEbrffr8SIJU68e\ncb0QxtxPfufvkKwrDkYHCZmELVLObSCpgIUxgzkhOfE2lzCfOHuPHYfQzkE6\nWgKjX/5d2LDeUDlAt9ZlSwQVJ9eAtb0rwOw7B2SgWzgopKghVE4atqf5oRrc\naFzgC72x92+vn4gANf6jT4368Ha27Cq7f35m3BSNhhFKS6+5cCpXuv57Jrk1\nAipJQWMQx2fhi8Kf5KBYwm/uv1knWvM6bpXGfu/ZdOV++vR9ov587GiT2SDp\nyu3F\r\n=mrM5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDh+yeA9wrc4Mb0Ee8Jah1w6OCQOyDaEw1nxJyIVoIJOAIgNSu8F5DB5t3uMtITGDGqqJpPdYGNSNCgLlEa55XXiEk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.65-alpha.3-smartgroupviewtasklayer_1564110072540_0.45485691526080574"},"_hasShrinkwrap":false},"0.12.65-alpha.4-projschema":{"name":"teambition-sdk","version":"0.12.65-alpha.4-projschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"EST+5\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"EST+5\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.65-alpha.4-projschema","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-6phapxiEhTyUOfoSOEdEEPOQIsxFNMNJX7gcR8DWpRmazAeH95N7VtkF2CulAHoNhjEyHVxIEvmGOdVm65c4Fg==","shasum":"a1f5af237b1aa585a56ca2463dded84e070473cf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.65-alpha.4-projschema.tgz","fileCount":434,"unpackedSize":925654,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdQBWpCRA9TVsSAnZWagAAPGUQAI7AWhjkJNAUbAwBEsfU\nExC3gIuR0xJZdXh2peDdaRmwVws84vZc5I2GctMid2fnjPm3kc7OCh8HYfRW\n0yftspfStCO6+2bFKkkQ0XJqptwKHvqNYXRZ4rgsqdm6PI5Q4bI0IEAMUfIO\nU9DpTaGNbtHZv71zICnqutUF+a66qfPZv4lwmW5etgZmzpk1VBVGZ+Xyj5/S\nGYZgBew8vIPHLbGx459rtWieEB5HEPbxGutQS7juTgln8BHZLohLL4BXx3/5\nhK4DGEQLqqDjyc/WDGeWBTZwitv93xAvOZusqg2EfmF2+iXA1il8lMB/O8ar\ngv0vrgSJn8km6/TGfTtha+ooNdPe5aXV7oWIUeYutJdVPiV3y2mHenF69Xn2\nM8UTWxOcaE6HdscCRGJTicI3Y8ZckQpUCTVY4H7BispsOFrDaqbAropQU/LP\nAPxyxEXITbGgSUGbFQNYUk/RRV8Jw9wskPKGNFg9FFZTqIjeVlKwtCEcR4S6\nUM+gOgrt0mm5fQiMcNPWk9r2D8xSBAmOn+CfnMZZeJ+27dVLEVDhz7zpYQGe\nwYUsEyI55P7dtg6YOWVhpcbfFp1675WqpkGlr4lgFplOLgRWlf6+DBRfVhRs\nCuAYDuZi+Bt2s7P28EEL2DGs6YSQEepamftCE3b6kIGYYmecvvhuEssKkdPr\nNRrn\r\n=v84r\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD+29f8yF5Xpajgo4dOXAOtmsvDnTFQO/wrhhHaMSk4pwIhAO7EO7UUQqQLsc4RNaxe3rtPccqwjUctuQW9ugLr/35p"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.65-alpha.4-projschema_1564480936535_0.19382757139343543"},"_hasShrinkwrap":false},"0.12.65-alpha.5-sfe":{"name":"teambition-sdk","version":"0.12.65-alpha.5-sfe","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.65-alpha.5-sfe","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-3Ha5CJaY0PgBK9JTUOxXIWM0Rzr4zoyRelw7TrgXOWnLiMDZjJPHuucA9le59LpvdNnVHrvIBrcmouxpBGxetA==","shasum":"6d772ee382df69627d38ce1ad00370320f2dc1ee","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.65-alpha.5-sfe.tgz","fileCount":437,"unpackedSize":928549,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdQTxXCRA9TVsSAnZWagAAls4P+werLzfqDR7S28HtqXlr\nasPhf5vO9a8BJbJ9dw27hG7oySBV12iOF5H5FahPuGdaxORT21/guySjq/oy\nm6IesIyBBsaGuMLIKAVGhDuU77ZbXlufDxRn5XkXgT9o2bl7uE8iKfhF3f6z\nqV8ezTjFRKFZ+Gt5twDDUtx+ElFtDwevi4HL1j9B3wmyjL24yqwX3QeuoBIt\nB2pSk6S0JD0P5thXn+/u2nO2XUXId1HKy04NCuGxI8iwJxktomYlayQDw3G1\n2Ggi4eyeazOh7oI6fhWeuSGz0T/Zc7b/JzLHxBctjW8Qgl0gaDZn43E8aL7C\nO5mM4i85U4ZPauLBYu2+R34EqcHL8ckOgS2wGwTPbbncNL6NhonnmzOzx3yt\nuAZjTY1qjg6pA6mWYsbXG1uYBmRetmAdMOoIT4HRdT7w5XVG0cYv2W/19gXG\nRH12EhGkRMjvIlfNlRSqxHNI+T0WNhyOkRUBcAYwA1kbjseuFFLbnQNsK9iJ\nksK9+wqd7G2HiBNJipp8ohsPcTFdsArVCmBR2X2wkLGie8zuL+yfOkVKEBP+\nDvVRBViID3stBsnIC3mOQTk+XVNG/wB7mLvdj8FeR9ZajUQAR4wYQtbHXpcJ\n2xGHyKxFGPi6owO7lrlwowx8tmLInpafRSADKafDLuN2K3oH1gSq4m7GNmlr\n2tLU\r\n=zhr6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDiJrcoPmEKZzgevhOZ0a24laUS86TjrOaZll8paj+aKAIgHdym9pxbbI00ZAv6xxRsF71s2EMyAU3x+Ihb9wWllY4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.65-alpha.5-sfe_1564556374678_0.5076906627165816"},"_hasShrinkwrap":false},"0.12.65-beta.0":{"name":"teambition-sdk","version":"0.12.65-beta.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.65-beta.0","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-BQu+GYTDTDkZdz6dyebDOY+1n0jngkv5YqKKJfPAjmzx6bSm6feUMSH8NB5mK6m4Va7yCYUK57/OMdIp/miuxg==","shasum":"9cb056efbc497a164f397cbff2d7558b5a733ded","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.65-beta.0.tgz","fileCount":437,"unpackedSize":929024,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdQWunCRA9TVsSAnZWagAAQcwP/1KutmFJlxKleuqkRHxe\noQSI1v+I3y9vm9KUoMYvq7TPRh6jbNG/HbYycKEZ3eBM1079K0avaOnRoEP0\njhPYGpL5N0Bwo+g6iftjyznt8qz2V0P45Exxg9bgJkc89UvFTU8LtogQJE/L\nFaThcgvrNOG6CJ9A0Pt/vOjQyw3V5QMFXibmO3jP7eJDbgeMFVx6NWymIxLa\nWxqRCeFG1qK1acuhYBfrSaU1vleNdIY2cryW/uppuKHkKUURUiWy1CVa2Acs\n8I1eq6OrSvoAHsaGjoelJEuXZqLL/QjpCiM0zL2expwVS9kZg10C8+TqX7eG\n7EFXu4w3cl9KNBSuRiTgoHAILvdyRUQKwYUmHy/sNDAa/rs1tfOweq6ZkVMq\n3hizZoDXu1oJF3wdHwYw2Zh69xNe/XN5MG74lvNURRneGpnzq4LvYMh8bjT2\nTwKBJ1SZ/YYRgvgs/uCno//XKFhk+IjVtHSkV6fGtArsRy5C+OXj4h8bM35M\nm1CP3zN6dSNPDcLi9gR0L6zVWvjtsZRf1aizpdLonLrVsV8tTAIjVga11raW\nt2V3EMyl8MVcE+g+BDw4AU5vXomkja8oVnBNGXOni3/fGZJlm1v5RyK2o0oV\nLCQzFYIQjdih4BPvWXLmAPY8QdoO2T4B4XzPYAL/XvjaZO/8C5TQDqBHa8CZ\n0xVN\r\n=kr65\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDDY5iimR87tRume6Ql319rqcZl8faBAqdMhzcvOK+/zwIgTNjHB2ekQRVj50qwbdSdodqaKYmWksZ0Wqgnf+T3dww="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.65-beta.0_1564568486651_0.4787033540329273"},"_hasShrinkwrap":false},"0.12.66-alpha.0-smartgroupviewtasklayer":{"name":"teambition-sdk","version":"0.12.66-alpha.0-smartgroupviewtasklayer","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.66-alpha.0-smartgroupviewtasklayer","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-SM+tTo10F6uvJEGh8Gp0gjpiAy3zqvzuPu69n5JbKfFheKJPJ7B0OAKBc9mqdFyO9Dt53W5E0EaJTCos1GZ1UQ==","shasum":"23ddcb1a8146be48889929ce2f47c2cda917188d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.66-alpha.0-smartgroupviewtasklayer.tgz","fileCount":434,"unpackedSize":926417,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdQlSECRA9TVsSAnZWagAAUr0QAJTAyvu/OmAYTuaP4M3j\nJb96hMDqq2ftEj1V4dyF3LLXHrL+UCfjs8g/GLxcePCdwhVjDQlbDV+FkZhF\nG6aApq379KEMty+blWCcuh0sigvLh0GrR6GRYq2liKIKfgyuR0RWlTmC4Ql0\n+QMU6AilXQx/WBava0bdxqUeZZCxF/BXM+rwfkwRRqIRzRW3MUymfD5VcK5j\n9KVkOD18UjYuvgkbt+ax1kRYIvLxbevaRiiT6jqE2rnFZyb/ZXYrxaQlDNzx\ndFB5Bvij9D5ms9cW8djao66A8E2gB/LQOkuhflHDO5Pi7+dHA1ComKUGQc6A\ndMABTwKTwloroRp2HZuYkG1LL+/f3jYuTxtlHj9sPxxsPMeH47pzww3LIOVK\nOFuQc/JelAkyhHgvrYgkL87BhfoXo9VbYHxRJuPMKYdzIxiB4Zn8lqUlpVt0\nN1d2/Olr6bqhHVrc2mFPxM4m7nmSCBs1Q0nHpBEHI9EpbNTrDBUXfTNGegeT\nmOkJ1OMY9m582i4kebXpcs3vcCdUkguqaokUasq9YobreZkr20MxhmBZswgI\nALsc7fcLmLD2YAxy5XRKZIElPUGvohU8rgalijfEqdJpFWkQvloFQHSSWQWI\ne7a/wW7HPAeThJsz7rmRaN/7cj6k8n8l+aTVFz+IA73h9IDUTLgdac2RZj98\nuSud\r\n=f/+y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHFLc7vG8I8A/4Mddn+7Nuyo2JLank7ctizmvIzvjBnlAiB2ag+psHax9Mq9/JChZU1FiWR0VB0uiu8QcWwNvx3Q6w=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.66-alpha.0-smartgroupviewtasklayer_1564628099883_0.24002117242607257"},"_hasShrinkwrap":false},"0.12.66-alpha.1-smartgroupviewtasklayer":{"name":"teambition-sdk","version":"0.12.66-alpha.1-smartgroupviewtasklayer","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.66-alpha.1-smartgroupviewtasklayer","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-pBXGGAQ2BX0nVNAgFDprFIIosAFCULSl2v37gDqxIeRGrSEJ+enf8S7V0LoXT0iXoPiKCz09l3+W59hFulEFVg==","shasum":"9fa7cf854517fd8dd9f4abf2ee1cdfcea4fbb209","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.66-alpha.1-smartgroupviewtasklayer.tgz","fileCount":437,"unpackedSize":929564,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdQlmGCRA9TVsSAnZWagAACmsP/2G6H51YAkFAM6k4Q2Ao\nVhaxSz+Nks7TvygvUGotnFKX/YMzd1zdddAmLD5Nx5p3ZCwBvYvKXI4MUdAY\n8Lb5hE5ZG31gF3NHk1fXQyP2PrJqHrSeG4AEOee88Ix2zSiI4W6kE6PX4ZiZ\nHHKhsi6Qc/eveiVR51uisnHEmpyPIjU5gNWddQaWIytfQ76tI0piMEm5ZwfG\noUongqqrE1GTJldfKWNkHIc1wJK8KFC3xVSJlNgPqA19uvg+Jn2wmLL/tg2l\nF12kTKwQHgKX/MG+WiBIaa0+mNpbWJzF6FQ5I0FuuuKehyjr9jAMjKZnb/g7\n94597VMc1Ns1HoRuUdalht0/+EO1h7IWwLRkl/B9XP7Kr9yTHP0Qy8ZqNRuN\n9Cy4+ALVPzUjloe9IlzVYbijpljN4N69wPKVNw3IR4kS8fy4CHx+jBrLBfV3\nOAHiIjlkSyFBQ5sB9LpawUcpAQ8YCwBePNHJQ69zhsaL60tab+tmjZAvj4ZC\nN9LPiATt5jhT67rk5AAHqjsPjAu+prD7CQ4FolFIgBKZKvETTiEvjKET85yE\nK6xNghHr+/KtgjvAYP44O2ys7ui24m6Xw/jpPagEHrCAlsrgfqf+WcQ7re3T\nYFYEs2WZAr1Q/mEN8sDtSLXjFxHeSjBtZKdptWI8hHHvq6nAlgrcZEqqIjpt\nSyUK\r\n=afh3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICJfSocLyqLItub+ua7co6nJsfUxzCJuEQ7g3x6VCAJ8AiAzWfIqVkIYBd5+bqq5++y9e2Efgu35cFk6KNvaGI5vqA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.66-alpha.1-smartgroupviewtasklayer_1564629381575_0.602498210047353"},"_hasShrinkwrap":false},"0.12.66-alpha.2-asyncdbleakage":{"name":"teambition-sdk","version":"0.12.66-alpha.2-asyncdbleakage","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.66-alpha.2-asyncdbleakage","_nodeVersion":"10.16.0","_npmVersion":"6.10.2","dist":{"integrity":"sha512-omlGekos+quHyaw4Qvy1m0IKbxirhqAX7+rvdYWBmsHfw+6F76ZmeDWpryHIpH3FHiknFLWIrLldcfPOeLHSWg==","shasum":"2a2e75ae0baf369e12a7a24b9a61e31864835573","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.66-alpha.2-asyncdbleakage.tgz","fileCount":437,"unpackedSize":928974,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdR6TUCRA9TVsSAnZWagAAQtkP/3kgM2vWl0iiqbYq3wpv\nW3EkH++swDwnyrhBiBzPgxJTx5kpdASLb1xpyJsSIwoheza63oun3lF5gQth\nmbfDsf5nIO0BozD70npB1vl3Ug296W3rZVPMyVJdGqiBCsyV+/8Mwk3LyJBM\nD1XXG27S8y6e3eQiIrkoMh2/qrD/OhVI9zmANYgd1MhVkSwMy549dSxeRHBf\nHfyJAtx4WAMvD6tf13BuaYfsim+49yiLeXM7GrQW/4r54mRqI0jHGFnfv0eP\nXj138WwNU5Mp1I/zVnWeQXu8Y6TjVeGuqutmbvCEnS3M66KNwCJ0o+XOVLRE\nUTVqcApRaieDSvBDZcNGx0AGtsaKC1qA9D9TWf2l601KRsMjw5/YQeX3dS58\ntm3Ni6WfgwZyczgABjBsjiT1Yiy0Qig+bJgIz8bi0cqevNB4qhY+/YRCn7DV\nDVm4q39RSGry3xlquXapkk6FxkzWsmqWDEqGxDAaEncqYpceQDVlrwL0JFW0\niU8FKrB/k7XVrFGafgDF6UrhB02Hz9glUt4Ky+tv/5/2Iw5Q1O4decHBDlaC\nsW77zRCaRDUb9Wfv7x9pzCpKX1z1a0MLlHhpirR3KIg2hqXqHAj56nRux/+W\nx1/jxk0nA1cH3KDtPlR0S3eHc8eFu6kLq5nqiIciAdsENb9d7/io4qDCkx6O\nve6Z\r\n=8m62\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICm+R5w0ApZ8Z8KFsO9cmbJsqBYgrJ3qMZlLAJguuQddAiAJ0cS2HLNmZj9bN7vdAQnyqKsPzBhn6TZKO0skyyzUnw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.66-alpha.2-asyncdbleakage_1564976339792_0.05049475401638359"},"_hasShrinkwrap":false},"0.12.66-alpha.3-projschema":{"name":"teambition-sdk","version":"0.12.66-alpha.3-projschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.66-alpha.3-projschema","_nodeVersion":"10.16.0","_npmVersion":"6.10.2","dist":{"integrity":"sha512-kVOnItJIWJCpHIvppPfzqBqDpMmtCijZj93ObZZT9FBV48vKf3qXDusfsEfzFQpnUJhUZXs7tSHPOiajq/cgDg==","shasum":"2f142c9cfc8d41e410baccfbefe92c4c82211450","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.66-alpha.3-projschema.tgz","fileCount":437,"unpackedSize":929060,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdR8j0CRA9TVsSAnZWagAAIO0P/Rh7iWqKjwZ7VPqrN9Az\nlfUgycwI+CZuK/QvLT87Sih7/BqCM9JKr0lF0q7syOZW3J5XGBq2/4+PmLGr\noWdjubTQFNsxce5rOMiuwIEyXkc0tP1nRo5lTMmukU3+R/gdsDTRiafvDyI3\ncMvaROj29SbcOQVN09FG1NX++bpXJlufvWwaDUPgqoSs0INCDvfr5yzILNYK\noruBHY6y5Mt3CIZRAjVuPURYJP5cZbr3k2S0sKodOcHO9HhbZtzFxcM4nyKW\n1VsweAnj6hwlhpluM3NtJ1cQ7T792UM+zPT6ZkiNif9LsT/DPyoqPwmcENpb\nQ0yLchGwm3a8ykCv9NvvQPidQkISn+hf+EW9D4n2/Un+W3Z2Wi/bhM/KQKJA\nl9doJHxESnviL6NP/yActR39K1zbHKKTW1UMR4s1NFfgVEpnXSrQioL337SK\ncPgUoKXjMzJcmwOisZ0KANnrPa7ctDlpMwGGgXqJqRxCc1qUeVqAqLRCjbXR\nfp38CbEieIjyPeltcui9D7HDmjOzC/db7CVuwp+FcjYgDBhRHfSlfn9FXDBK\n7gMpBb7/82cwgv6i5sTsLJZJF9b9p5kMVGM/ES3Mzb7yGFoQUxPmgDrfenPn\nsTRPY7OWxscNu0LEkZwVygk1hlIn5ieXi17oL4DaqbDCUHXQ5v6YXN/tKNy8\ncalv\r\n=Jdry\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC6P5B0p1SUS3tPK4P41i3OusQwJa6/1Vva16N15UEzoQIgI1VW2Rr+OPRDh5f5KGr4Dc0mj9U9M1TMnzf9cVNQNwA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.66-alpha.3-projschema_1564985587389_0.44699430567867116"},"_hasShrinkwrap":false},"0.12.65":{"name":"teambition-sdk","version":"0.12.65","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.65","_nodeVersion":"10.16.0","_npmVersion":"6.10.2","dist":{"integrity":"sha512-8ZlgcgUXHGgWFpIfZ0VG2mJw7Xh2yHYYEYbvqqlgr6r12MI57dCQAB94e3/vG0dBPzhFTboxaQEL/tLGwPRf6Q==","shasum":"bb8824c08f8b9db28a104b459b82ce76ae755c11","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.65.tgz","fileCount":437,"unpackedSize":928951,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdSjpRCRA9TVsSAnZWagAAtHkP/1iJvEl5J9Ilt15i54sp\nMVmkPMfSzkRnoAaEcPzAOkAWJOJrRwZ4jdr7LYK4jTl5+BhySpfDDZX9FY2C\nWF4aw8604vYDH0qzGkKAYSjEMyQ4FkrwcouRCs9RRPd+1g+EuEmEMnci3Jky\nNFVuV+trbE/VH2sXe7NPjQHA2w70gtUOnQcsH+xC4zOLe+n+oIr8BA5caLiS\nd8FZwntCpuhcwY8bQSGFUNJ4YJzo3i/cgcKiZMZsrCFmVK1NrrgCLTTxGPpQ\nfKHqekqp+MlN3EytiPoPl+zhb1XaN/6FN7OJg25dD37a2dpEcJQhmMqhULlO\nUgAhErtMCSGgemp4ufXE0bEz4kPfmFokZr9At88ZVROGx8w2H5N17OJQMI5b\nZ2wZup/wV2Pde13HYBe+HYinLF8SWTSGzEqPXPyEPdd2HaJrmdjXnQsjQPsj\n8NmxSbd8x2VjsGZpLddHd4FKH16O2K9BESFDUNVJSldNtoZh5OBu7sbqxZYk\nwQb8sbLPkdFdNQOgiebcryzCDGfSC/2ugBxYvW6OAhCKCp2niJA2tELQ5OM3\n6YvasHj7FET+9nBEYLdlxdVCmB1MBQ5hqvzDN1NdLFZIMqiwfVgWlrYwvq8o\neiJ4B5bg1Xtqi8wbTO32NIJ+2Aoz65eWJsPu/X9+U8cLgTzUVSWUyxqhLKG/\nBl4n\r\n=dLQf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDmE4LDG1RPsHP+p4WxvUxXNMlXIfJJqfSU2ITZA+MVSgIhAMxN2XHS9C0XLyvvYFdUaCrHmqbiCqNaKjiyuCewJ92/"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.65_1565145680317_0.7147485200241919"},"_hasShrinkwrap":false},"0.12.66-alpha.4-projschema":{"name":"teambition-sdk","version":"0.12.66-alpha.4-projschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.66-alpha.4-projschema","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-oxQVZMJ9xFk3l6+f9/NIg6+a+3hgSWeQgAv3L9fmwk4+q/RhVh9uJUDxfs7IF+Q/QRKzeR9f3BoNUrzOiBIftw==","shasum":"cd3703550a102aa86f0cb94a6c83964a99321b02","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.66-alpha.4-projschema.tgz","fileCount":437,"unpackedSize":928994,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdS8XNCRA9TVsSAnZWagAA9k0P/iEsZdem02EEwgp9XqZp\nmyOgCjai9kREyiSQo/xXdMoozOGXzrbjjlGkAHSH+AhZD5fM7A/kLUd9bl/l\nEfEs2WcwvG2D/IeoTMFG5OfI4wI7g8C6FdlC1WhB7jHETjnPsyhjMgoxa68S\nHybONuotN+bDAlnhwDizUV5BINOM5O5H8W4euvcJSJ3S6vAPCklLlu8pS5c7\nrppcdH5M0Hp8E6F2PinZ6JFcdzm9Ii0c8IV3wH/HLHdvjweQ2g2y0t+p5vZ2\nQuyt6Ri7gW5iv2fvEEDNQChb0fsTyq4ayZ8fJ6FbsdMtBMqum1Gf3n3F3JxH\nXGwAukpXLzQsySytRFyIe1DAXaB0TMxMD4BdD9MpAQCNRpXinLoXgkGxsNNL\nDtgpNM9I4iPcRx5c29zf8RL0CXV+H2bJnYlp4HjlisxZJGSk78p2sck9gIU5\nkqACmF7X/qeroX05V28uDVWuJihbHvjkHgdiGzd08d1axZ5Pajw1Gt3nz2sd\nAba12TvgmRPGkh3M3SMTwhhduoLZPYsqwxAicyOjJIgU5A/le8zFW/QgIlSo\nLcHKYZYBKcfDJrCuGTDMC958aWY8uDCgR+J4UFIb0ru45i4Qr04qbeJBWQZh\n3w45hWwnTRZmZ481fGusq0FzOG6RSVVzW1tGUyDekEHeaNLtmXEjOr5FzkW2\n0OyY\r\n=qUQg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH07atvkE2Q+HG/rXu176scEO2BZdwL6Oxm9xXFQMvvIAiEA2ID56Ld2FdkJX3VKcTqMgGEtu4V4ruOOqiU8N887Hzs="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.66-alpha.4-projschema_1565246924950_0.7678498973076955"},"_hasShrinkwrap":false},"0.12.66-alpha.5-smartgroupviewtasklayer":{"name":"teambition-sdk","version":"0.12.66-alpha.5-smartgroupviewtasklayer","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.66-alpha.5-smartgroupviewtasklayer","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-oqhN5wDmwYoNmd19qCZk4eh/dCJHbjIO/V6ugxz1KFz9B+2XMUp4sTS4FzW6Yxn8sL89phBgkPqGkStBcj7kTw==","shasum":"9ab044d3ba711a9bdea2bfa6110f9d8cd9b7c2d7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.66-alpha.5-smartgroupviewtasklayer.tgz","fileCount":437,"unpackedSize":929498,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdS8/tCRA9TVsSAnZWagAADlIP/RbbHg3BTugPowL/mV6d\nG+eAqgfEjFKc05uL6Wt2r/44cRsqZ86skpxxJPimPcNtnOXwkDaEjoJ3yXvF\nBZ6L9AMG4aoIBCbQL09IFW4JIe+7WqyI/p0e9dPSmQHhO3PGbQNlnuYO38HS\nIk64QPnKB1K0uSQOFMr3QN6D39XF3KwXb5jBmB0pluwj0ZLRMhKcwL0fF9So\nzp4nMmuNp5+dcLgL4JisW4WKq7bqPClAdWKuIu57dkWxca4Trsm8sk02NZlp\n28PGc29Xawa7/0oUAc2zkwH+53h6e/CCZ6Y3xxfA9jv6uYqH85yOOOawcZKh\nYLiyXvlyaLVd0M3jQj8BC9NbszBmhaxRsfU7US1NMx5EC71/SgKz9HO9UB4D\nff+l9Qnhe3iuUZt4JoVyv6BCGeL0kXKgbpLkztLTlEBnBqvyTmf4as/wBmbc\n3XpxseKWs/HKNe/ufmJPIJ0peUymgLZaZitJbHB1zmpB/M1wPhlcmiMjW+jB\nXGVjVQTrDlLARzkPXOmFS3cZWJ407hYOztIbRI+5uszzwxgOsTNxU92QSpGo\nJ71xJV/x1Pkr0fv55XwEs490pGXtryO21Pzx5lnKeOb8IQ9VqPHvdc7q6GIz\nHoiq+U3diMgu90k1wFwR1jfoNual09S+FBr0/15E1lD1kMf31/letb5rVaV1\nKLVl\r\n=8QpR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHdqIhA/TYzmmpATdo9wktrD55uTW5EILE8fBAlU+uU3AiEA9U3mDN5xGEO5CGnWGU1b5Qc+WELWC6pBaGfjpXuEpc0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.66-alpha.5-smartgroupviewtasklayer_1565249517221_0.3879505049999188"},"_hasShrinkwrap":false},"0.12.66-alpha.6-projschema":{"name":"teambition-sdk","version":"0.12.66-alpha.6-projschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.66-alpha.6-projschema","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-UD8QeKgGNx3u0kv2c2Vci6YdnPTrrkd9ySi4SUMFPJwArKbfgXuz7X2c90gedFwz3Zf7LrlMcf6K/Y5jZbaUgA==","shasum":"5286537ebcbae85a31dbf43c15dae9bc167fd59b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.66-alpha.6-projschema.tgz","fileCount":437,"unpackedSize":929509,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdUi9ECRA9TVsSAnZWagAAM5EP/RHiotBOuMXb2/M2CF16\ng2Gmg0CtiUMTzChZ3hXxAiOstqjLDXBuRpxNzkraG3vOYVKwrf1WfEMt15ah\n55WB+91xzvPMII5HAuYl38Gh4WLLdh8ZQR217uOjNnyiBRaciuatdRIRwNeu\nBhpM8/Y80/TmWFM2gKvSdOImq3rMilmOScBTT55VmzhSnvaHUDjFLoBg2ROX\nT7ImrVSuejL7m5lH6LjGHzVTIiVS5ieuKZ9H4vaZv3Fwbab18tJ9zYFf23z1\nc+umzaJqX3ek/p/BV8uLvJ6nMWvRgg3r9lxMXyl9h1j/8kT3AwauB5+DFBHo\nK/9koQunwQ0wWs3XAY1klXZoEiGKQ2jANoFjP4h1jwBEKreIR9kATWLWRSap\ng4anb3JXw1pnEMX5fTfZ4c7G+1fmIYyO2SzdbFtJnlfQ+CfUIk4MBKA5a9FK\nVNgnamYOTK0NxTIyUiKaYs8MN91MJss2SB0AJ+kpjtUPl5IWlRgr+t1lD8Gz\nPw0/mFJk1EcIMYeaY5tPPYNV9gXU0CsFRCmZUU0tg6s44XFmPMBm3IjskU4Y\nuJTB9pK1XSyZliDqLjkQPfOCqYkH/xN2E3PcP2aC3RiuVXkuIWYz6Ow3pyx4\nHcF10PujYBIr/GRKmvgTajzHK1IWK5EkPID+axXjd8aoWB+VhTFALKqkWwSg\neqCs\r\n=yNkh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCgzudYJxjV1rFGc4aqUnkaB9zIGCKQzTF6sPNTki2ITQIhALJh4VoLfVE0txTyYo/f52mMhGcPLH86yWM5rCIjWd8P"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.66-alpha.6-projschema_1565667139990_0.7770160836660884"},"_hasShrinkwrap":false},"0.12.66":{"name":"teambition-sdk","version":"0.12.66","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.66","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-RlAIQJfNgTaUf9PIHrsXn2fNs9+ibqvS0hutZ1uDyRAkgRnz15QQ4rxStGQWavJ6ESiIGqeJwYjR+gh4PqCxvw==","shasum":"dcf75cdd719341adf9efac91f04eb86622592461","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.66.tgz","fileCount":437,"unpackedSize":929199,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdU7zrCRA9TVsSAnZWagAAXKMP/2Pr0TUIzJxx7Z5loW6o\n29LHdAoefn6K6CcW6SryZKwFa/Zk6z75oekMIXctcpU0YfUL9qouzTFUkXRG\nuMYsrS4o3dDn+DNjmqAcGlTDIePt2rdIK30i4cG9C5aF3+A+Pcpe+5AVxZQp\nAlPI6bistoQ5ev4n1YR4FckbNrbLJXLsidfrymtFav0NMbu1zTM0Ln19seRy\nyD404m6Iiffw6bT19lsTFVLr6DdAvZNZm0b11JmBKY1T1lYewXU6qox2U88v\n8k58RK+fUBLkh4a3T5ObOFoxKl3DvL1+1mMIcPVjHMMWUg/VuOOl0V2tfeiy\n3wwYb0vVJ+PhuNbGGgGoe3i2eEPVreZx4+zXGYsUkNsvMeC6iMCtxNRfprR5\ng+QK98lxuD3LSsPXsXYJQkxMRA0bEI8CcN5m8lgWOgI0XBRHxKPHO/t1LAoq\nxxXBad2/QTRA396CbMiIDUiY8MmoFzsIKTsgSCCEoGEW79XMclWkZkqzVsWX\n/40/HzbvnSYB5FfVxycT0Z5cKt/evCuIXCqad7DxuQso4kZNSIbec+mx31aM\nVgq+zcENZQUj+XlcXlXJrFBXSiLvjTOUJ/m7sWu6B6+hXbB1e2hibSSUUSBa\nzeOx/3Etb9O+Day58TpNmBYH5Km643al4MSXWr8EDHXp8ve8cI0CklqrnFxv\nHzal\r\n=LIu1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGksmLhZVmm39GT4HJv6QzCKRMi/S8YuRTMPXD6TCerpAiEAyCs6kZ+IGHkADv6xZf6ye00uTc0pV5lQ/zugWSufXe4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.66_1565768938641_0.14181408665176876"},"_hasShrinkwrap":false},"0.12.67-beta.0-fetchshare":{"name":"teambition-sdk","version":"0.12.67-beta.0-fetchshare","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.67-beta.0-fetchshare","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-m8jKsPVerQHSyNm0S4gqT53IXGleGx/UDvIYHbVAbbwOBi9tJEWmkYbUC0MzEQpoXNuAwxOgmAKU0rB+vGvwVg==","shasum":"3ba752213f36c6beb3ae07aac76b7b1331f867d0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.67-beta.0-fetchshare.tgz","fileCount":437,"unpackedSize":929822,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdU8peCRA9TVsSAnZWagAAUgcP/2Y97hZs7llKoUWq2UCm\nbeUqTTuKIhRx6LgyPrvXFgcI2LH3kTNXPhaR/bU1a/EGQWNO/YpMCyKk0isq\nve1LmDMm1BNvFIIwp37sqcYWPOh3StqiwJf1LdD5IUfjSRUsuXTnhiSYS4/E\n9HKAm+iZKgi53bNfyPpHq/UCiYrdCr3tFbZKowFM3+rXcUAkuleAObjOdhfL\n8Q2e+/KzNerJ91vW1+IAXcbv4c7hNOCXvg5Axi+3/LOqYIh999KdzGgbEHQi\ny9f0ZUk0aBPGRF/TSG3lYtYhIe1PlSnMbyPWf/4xWXB64TC0AB4LbNYpomKE\n8sYKOadRzAeKwC9iK8blRDWfO2RiIdB2DsAE6xau3SCSbZf0AYCW0hRL60HM\n9T6O3NNd92dqFfdHr5AUSOQk3s8cK51m3HJCpjDz2KGzmH7JpDLP7UOfAd1v\niM3L4jjrF61OsD0kdmEe6jaEf9jI9piQyBGpIA9Rp1j747TfpNzVUZAvTvrD\n5fNIAPqP6DGxpmDDMi+yo1ZKEczXRPUBWaqYsr3SiLSCBxuYs8sf5WE+GxTu\nkdo/PQO/ZVjBPJ+zUYQNlZDiZWXnZKQoy+BzQQ1Jay+eHwd0tbkm+Q3D77rc\nRaEYZClKh1SabJ3at7s5ysLFjdPI28eoglAV9lzqG3EtGCNyarkDB2Ycb8Va\nJF8V\r\n=cq+4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHdeHOLX+EPU4+UpVkEQoDd/nvMVt3ufpUJfDceMl0UwAiEAg0D2gxcYEdf9uUlIyYYos9YY2gqsXfeNdTgygDrKpdU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.67-beta.0-fetchshare_1565772382082_0.48924858819260986"},"_hasShrinkwrap":false},"0.12.67":{"name":"teambition-sdk","version":"0.12.67","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.67","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-2+P6shOUopp64AXsfyIOVqksdH6zconP1I1jzZbDTpjfZT9lKONKRR7yYu35xcc4ekH7gp6hTbgQ7JTzFeSSoA==","shasum":"d0ad1a779742eecff5d733f7175b1dc025baf0cb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.67.tgz","fileCount":437,"unpackedSize":929804,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdXjucCRA9TVsSAnZWagAAZ04QAIj0FTRDGYjV5Tt9HRL8\nGZu6JYmuCVzAQQGToPa2Qou9zVHMt+0xFgTGjVLUTFC8DIcKAgir3uRqPq7A\nKwwosua5h5/8+d+RbbDu9GzaO4MvnrUHxz/ZXhZYTnHDgi8EWkle2tcRKA1g\nLln/Vz9GKf1Gl4jzz9jKOqpxx89gcc1NATaIE5bgM/q1VXVvAvlltZSDvFB2\nSxoYI6GSpb7x8U0D/JAxl10ecXh2AuzekfrF7xgJbrJANpTz9lvMn46TH6La\nOyifs+SJHV3BO+jAGkfrhrAo+RySXCJ5/6WRVShS0mxeY/hw0SaQAJWeKCDG\n8elxpvUNCMiaXqYID1gqXCsSS6XquF99XrvvEdjv3i+dAoWRUdIOhnSCey0H\nVG/JxcDJmK2TaeaiWZHo7dpzye2Uuklk3Vg2Q9M1US7tHsoSEFCGAKYIpdqy\nZMgO5TLSi/hTQUZDOVvR9BwkeCuaILkTKGE0M4dglXBkuj2VuwOivDxCQZT0\n/Y2/sqv8+oB5njxeNbcutXSct6kt1DnjU4rVw75EEgk40ARsgo6MAjqKoiH8\n3pFb58uZGUP+WTeXM5m30xNWueOS0O9IG7WeXyCDeyZf55b6UjX2zTTsLosf\nXqiBoERPAEqo6lbifg3plXAralhB1DEj/sNzIaTXFaVwivibilbtE3s+qSLy\nHW7E\r\n=3Yqp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICnXAF4Q1Z3uj20TfOtvzp37RFUhveExX/JL9u5A8fHcAiBUraL/m6wrFv5OLXBB0dd7xImmRHjFL9rYzTVCrz+S0w=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.67_1566456731623_0.8511487901749251"},"_hasShrinkwrap":false},"0.12.68-alpha.1-batch":{"name":"teambition-sdk","version":"0.12.68-alpha.1-batch","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.68-alpha.1-batch","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-BTA1JBy6FmQcULeukZJD3VWSpts4n7KgQncGUkpeO6Kx1OrmgAKfQon32wbxPVRsOQyJF2bx6B0rBOqxUBIAEg==","shasum":"0e047af55a39c46adea267aadf078aec87805ba8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.68-alpha.1-batch.tgz","fileCount":440,"unpackedSize":951959,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdXkEqCRA9TVsSAnZWagAAnRcQAKOMW1Sn1px7dOHLXWoR\nrWPu7xCBBxA4MqQ/Wus/gnje53cZVFP+q8mAHjRk2V4lQ9Jkti2oku9rVw60\nvi1tt49oRKUb9JUMghOp5uC6v27WC9j8ujgBQmZG4snUBFwsvl9MaQLiAmxM\nqvXS+RmQok31ELmgshy5Td80dblp7vWxPkGNO0XPBY+cM/bHKwI7SflrAnTO\n5hbeMzi1RFUvanh6vqlHf8a2SFN4n8lT6+DBwDudw4PVcFBMwdK1dRasTrjq\nwI4Gh+ee41JFATjsBh2Fy6oqDqdTG5NUg9AA/jw3RFwuXLddsw5kUDXFt9RM\n5KIkPJaMHBliZPedviavr1/pNhY/eU5ixGwn6jvPxdCSJNngjHBkmq5eH2E/\neJpg44gHnWdJKJWILW9eH7Urtp0ZGFbilZ2RlwVwKjn6THe3JNDtQjn5pxBt\noKvzaPZcfUwxH7ES6mMG2Fh1iT8DB3oXOeXBzE3mkDqf9k/FhR4fYY8qN/bM\njcAJ2MwkGEbfz1nW8td2eyGCXtUZNgQpBs0O7TQ0pqqwiXoudBpyVxceHdb8\nja6Po8YMgATloVoOme/ALhNwULSWacmivbjL2Gm3EHW7+GgNzN/3xMuXxfCo\ndNhPVW9Fgsx6wDJLPb5LeAP48HmRVLtUq0ubn1NMQqi3NAJPMg1Iq2f9L5D2\neB9g\r\n=lD3o\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBTlNkAVDnTv/eUs2eRui7fl5g0Fvb2hSxd3TudKIBO1AiBcjcFOAL87su5ILCxe3wiWq1/mHhIsnYASvwejG9MZtg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.68-alpha.1-batch_1566458154095_0.45374396006522666"},"_hasShrinkwrap":false},"0.12.68-alpha.2-customfieldsubtype":{"name":"teambition-sdk","version":"0.12.68-alpha.2-customfieldsubtype","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.68-alpha.2-customfieldsubtype","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-PiCaZbCRKSZvTzfu8WSG9AS33db/MiTSfArrGkLhlgw/J999FKshjYYxQ8K8IDrgRpqKYcID6jyKgndiqsmypw==","shasum":"1beda1ff339e2103db6743874fa3b5d231950363","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.68-alpha.2-customfieldsubtype.tgz","fileCount":437,"unpackedSize":930088,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdZe+fCRA9TVsSAnZWagAASn0P/AsiAXpJb2KEGFnOgB/X\ncfD3m2SO+q1bPE8ljE6lU1NfZCw1XTlcpMSpnIXvyX1RuHtedYu8dH4zdGMP\ntZ2hThaGbChmVJR3fNyAGJs5jKQqjUhBCO27Iea3vpm0LHJS3fz8EpdzAikV\ntYdgnHmh+mMG7x5h7TQGbPF9/8P1pgSnewTjArtiZge+r6V9ta27J5d5R+/U\nnneKiF1TfsXwMqY7GmUjN58H2kQDshcb8qOfekiPZDqk/t70yXxKhEispl92\neHAU1C0D2gx4BPAE8wp+ih8/49VqgD8/Ket6Wf9v3HGDHE2hu0YsVbONLjTK\nrU33VyKoC/qrZXdRP/yBdxXkFoI+kuNBiaAWHwv6P/jtQbOKaWnF6QN26l0o\ntoocpFytVscGKY8BzWmi7kAqR0XXH8vhhgAqo18mKu34KwoQcyp3KENkmeYO\naqL81f6ExjaZIz5Z6Tzr92SrP0BIHlbkGY92T7OESsLBYyy3lsDJsIJvDRNe\nxDknPTZhlG4nVNiJGO8EQ937vv1JNgL3stzLwZWMvwMvyBXOxav16+2DXX6Y\nZ4/wan7ouPa1yhDOI5Dow37M45HriNv7i9+nFgjFvfRRNkMk68tPLBg5Wxpu\nxCrqt0iE7DBKdaVvAU+s+l5pbzQgOAFLfrcXAEeLN4IqWqrqn3UVJOaXq14x\n6YOd\r\n=roAd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGctWgq3mZXIW9Dhj+rNXY3OAE2ldBYR1CDjczbPIqtVAiEA5HPhfZoRG8gzQnOlSOIkjhikRg/PhZ7q8IBXNFBZ1zg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.68-alpha.2-customfieldsubtype_1566961566986_0.21062590212832877"},"_hasShrinkwrap":false},"0.12.68-alpha.3-batch":{"name":"teambition-sdk","version":"0.12.68-alpha.3-batch","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.68-alpha.3-batch","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-n2zoNDDib5zU6+L/20NPT/gbbFrgTIZl0zMAj+9Bt31lnOSYi3P9cM5W1bXRA6AYPyybDpgGH6RLWHfns9E/EQ==","shasum":"aa23b8138488d3ea91183669e1f52008c8b45858","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.68-alpha.3-batch.tgz","fileCount":440,"unpackedSize":955251,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdZfKCCRA9TVsSAnZWagAAfZwQAJ8o4ufkWMiOxHmjIv8B\nlv+u24dNyVUKCBC4iVwOjZ9CWK2e1XNeCLRkt5XeRhCxxiK24ZfEe/FCQvj8\nA53c12047Yl+DafklCw1ErhlAHwv2xs7eLrMRkizg2t7VJhBYWQ/a/SumUxl\nTlw98fqOJ/51HzvwFHEF2gBoqmpOzULvhzXaq+fW3OV5nDeiIFIZYWBHyYDI\nmeuHWWf6g4wxrMAQasZ7wa10CnhU/iPauUCRo9smObybXZqIwkHQBJkaxA4T\nU2Lhy7iT62oBUbRcb8bNaPk0tI1/G5Sf+BMx6RL7i5vFCkngdMXhyUDti6N9\n5deakobCJSvrKj1zHpJGRp7v9vALN1wadEfAcLfREWAZpUeK5rdTe2q3oPsH\nLAmM/m5jk+/ciAZ35Kc6AO3GMWjSBLgF5NMlqQU1YQG674qPJFd9TYJ3STjt\nrOQ7Zz3GwJ9FsbgENDaECjf7InZa3RyRHPjKFZDubHLuZKAH+msBli5RdCQX\npucuVFS46aQsC8nMiVjdzYpO8RYf+QXLnAPkDSAq5GqwkoqDQFlEhhycpTo6\n0fgbkPGyYExMND7LABhvpLsTTL1AfG87NpKpZdVA2o0UTfS/C2iP8M9Y2Era\nc3a/SjJgoFUINhJDaOFNNdQF/EoqbNVqMbJIBvpJLYKRGtS3rc6YxmG+iqQs\nMWjI\r\n=1yAk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC1mPLMZuHNOZkeJN/tsiSQ0Edvm13QVWAI2DVeX4IsnQIhAMCU9AGBin1uepTLuWcY1bUMjStJjm2avWkym9fsaPOk"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.68-alpha.3-batch_1566962305785_0.15856695306747648"},"_hasShrinkwrap":false},"0.12.68":{"name":"teambition-sdk","version":"0.12.68","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.68","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-9fMynoKdsndnRgJLO1UOURBErR5uV5YKYa3Oe0AMWsObcU2N8J3NUP7P4ibzu+vJW1mfaUZAcbu7fGrrGnFfOA==","shasum":"36c03c77782c1a3947128fc8510c9422d569e1a4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.68.tgz","fileCount":437,"unpackedSize":930106,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdZfjcCRA9TVsSAnZWagAARxsP/RV//gO6FfSunWN+lnaI\nXndRl1Ez9pRuAl2huWMsJLpcwBQJ1V3QeEvd8umlPv9AawhTxfyMlUAcC94J\nRBsu63Ns8vE3PASlGrx8yWRAKHehNeD/ckmVXw2oUDOjfnROaxwwfSQNrPyg\nzZLZBczDG4So4PeVmtgcu0T8ABCybIKO46VOnaeAZAH1L8oAhFwmoW6HHCzM\ndsUX4o4TEWPXgb4PNaXiQkV0xb6ogZq00lO/STHpLzLKlD0NSIhhlWR9IZeP\nJv58kWBKXk1bxByYl6TOGnWV+fBf/DLhBFar3jprWjmQaJq+Lc3lku633dj1\nw1MiBBNDqlLwk+zShohwi+5WL65yUaDorgeJ7HVChH1BlI5aM7AfGinjPQ+z\n1uEjlHEGqm0ssODsr7uhoPibNBJ6qUmYMwoeMXCri15J33LqFhCY8wQorrx1\nntHlUp9Ui9o7/1HW1mxG13qA3cnzBSKeuk7oHraZuEedAWUqH9FLyRjKl9qE\nT8DpJ3eZbyuCVd2Jhn/mG1BVqv6wjH7HP55yP0fqEXux98q/QDx9mni/+xVI\nwkPp7Kd6gvj3HkhkDLi0tTWm4YpYR5YAfQRuUTsHFqT4KA37WC+zGP0jggZG\nJVp994jUZJRjIHbDb1Vu74OlxDgOEvC1qlwsV8aEqVpIF8AGmuOfDWnNHK3a\nojTw\r\n=R0WV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBfeKYOauqDwZ4GHVlgbOmkEeWYZmjqfJ7X2GMW0tGVhAiAHN0165jf+Q0+cjzhFPmpQ3hnhUvQ64u6KuD+Rp4aSaA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.68_1566963931617_0.5990969607455077"},"_hasShrinkwrap":false},"0.12.69-alpha.0-batch":{"name":"teambition-sdk","version":"0.12.69-alpha.0-batch","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.0-batch","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-oM3bORvcT1Y64bI5CeyknvT6uKJpAd40x1Wxb4ZlqmQGi6nywrV6D4ags2+6Aa8+VOpjjywXH7zB1ib0EQbsdA==","shasum":"e3cb59fed1b55e70d0d191e4d70f7fdf25d906a0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.0-batch.tgz","fileCount":440,"unpackedSize":957275,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdZ3SACRA9TVsSAnZWagAAThgP/3zLtHsv/Un2lhHnAXY9\nRTLsfo5WqliVUzc05ZXPtHrc6Sk4o+4YcsNLU3NhuoZi5fIaggynef5YAeZW\nKrP/3SesNccTTuSaoDHkBk32DZwEz3kmMNdyur9rGcyxd3jWbIJ8ea5doRbV\n1zmnbaWDI4CekS5XLK/eW3/XujdXuEl4CLBFIrIdajF0L4kjkNFp5lMfnMxF\nw1B5rx0nMSPUbpd2sklRQdfK1USaBmCOgG8Pa/Q8DjsO6jvG2csRbR5kHBfx\na/HEdnUXY5s1SYXcI3bPmJKPXAEik6M98VnXHFfGjSm2/s2re4GvVH2X1l+g\nGEQKvjVWo4t6xnoqYcMlP/Am66W5eQrpR0zZBhSfidvqDnnzwOTFcx7Utn2g\nqNUZIiaXIUJVpLMO0AzjRHNyuYZ6z9o2UFS9tUYvNGFdTFkaK02CaCuu8swD\nJzl92Jzze5d4ptmzC+XTQJXuurzfU7DyRYkgVXrIXmz5KMOH6SoAMKztbwYt\nE+ajFtT0VF8Y7L3a/XQEsSdiIWD69uLtdIsMV10rFMlgnb7KR72IoYjlZlNL\ne7o+snAjNmRB0g9iwWr0CLJqrc46lqTn6/hIYP2Ltx7HtWQttDD/Vxel/znF\n19vBSrb35CNOavAOL20ld/WX45WZ0R9THld7TtgIc4nGtUm73HnVUbpQv0Mp\n5VTl\r\n=j9H+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAkwKWD1HYiERSE1HD/6AmHWm5fkkQ/5yLy876zPzwdRAiAllTDyDWXGjR/Ln2Hfv8OswT8E/+msBIor7FZI0cl00A=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.0-batch_1567061119788_0.5850389732083319"},"_hasShrinkwrap":false},"0.12.69-alpha.1-sfc":{"name":"teambition-sdk","version":"0.12.69-alpha.1-sfc","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.1-sfc","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-XekUxVAnTOLhi/Ot1/+qbE8YlhttOEuA8tke/C8KcOQoyk241ghZYeYFx8hnoIDGyT4rpsvz57zk7D7FcLYVvQ==","shasum":"1cddf3c5188639c43a46593500508c7388abcaf6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.1-sfc.tgz","fileCount":437,"unpackedSize":930202,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdaOPsCRA9TVsSAnZWagAAeUMP+QB8BRDDKUsCtTJ1szNu\nAFCaGaSz9ZCwVadLEfrxsML/zHLXkKk6J8ayTpk6r1JmMyxJVV2qy17aOO/W\nNwiUD/lVPoeoZF6JfE59IOuajqUr8X7Bd3zIG9VnzniJhFFvHytJMN1SbRsT\nXk4AreL9EncWb5n9SQitCdO22OOqZBrxaIaJF+NkBiCIBtmrl2jIwAWDeV33\nA+IzhR5e7viHsgGKizA7GsVoU/QfVCtQqUW4KvtCpx9yMtevZn3o1kRq4YNy\ntQ5jklD6+SF3benFHESJ997XwYRdYQ+WwhNS3Rjis4x4mEpBkE4l6OiViR/4\ncyXJFhtJ58SGyLdnUSIu/MgjYvtIVAoPW+u5bFB43Om+ZSsS/nrfNYdySFCg\nsXC9EdHpVUDQICHOuSqkRhg/RFfH9ZYPf0ZnBlFuXj0OweP5OBXtQwFP8DkD\nrM41h9vynSNYL6gPZoAHvbJf3cGZDHcVEHdsOcg0yb+8knVD0a2usaGWld9u\nMNmGLAB1VD27JDU5H7qX+GtdwgRY1b+pjJYihJDsUUcmn6eJcpyxb/yXkAk+\nGZgoCfNw9or2MJVGpUJY0pFVA1RKLDQrymXS3PxXIXAic51rpD4xXrwRjeZO\n3C9VK9zAP3EqcnsRqFyTeCib1Y7vvmhAh7ZbaL9jy4QwT6M6QILLgbo2efxe\nk/AK\r\n=Qq98\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCqFeJZxEQhtzU59LbmFUwvPY1RpwuVjB6Q71Bz9jRiZQIgPP19MKnOcg2Mknr49uwwkgZb6xkBTEQPZ3MR9JZ2ufA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.1-sfc_1567155179611_0.36761969681367"},"_hasShrinkwrap":false},"0.12.69-alpha.2-batch":{"name":"teambition-sdk","version":"0.12.69-alpha.2-batch","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm version xxx\nnpm run publish_sdk\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.2-batch","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-a31LE2qZ9gAm/CoHYdG2X3otaer9Ye0h5Lg15lu7OU0BAn9GNcvYS5l13itUXpDIV+pLvtSlE/XmF2npk4cN5w==","shasum":"925e0165678a074f9394a2ec9e1e4718ae5f7e08","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.2-batch.tgz","fileCount":440,"unpackedSize":956927,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdbLX6CRA9TVsSAnZWagAAQQEP/3aKUPWa9hsQJrEnJFjB\nTx2W3+MoCmXoKFUXahKO2gYMVH4PyQ081ktMauNpb8vK4/U6Ml521LJ7EkoL\n+LwFHSRuneNHmqToFEpEPTrSIM98H/BraOk/PFDtOwr1eX2D+1GoPHJdetIL\nXG5Y/iQYfKB+NKDA3lC2yd7bCWxppSfDVDMzhqVkFWHK0xQlI46bPBG4NhXk\nFZjYAFasrdgvAp1vADsi8CZgQGgSlWjn+xsqKLCjEjaUSEVC7WdtBGq8R3d2\nEQlRnaEvaUzMu1QKPB54wVY4eXqIl28kBR/c8A4+ZApFDYFpJvKiuFPL6R5n\nqE+aRdt2cOCHXUFXiwebVjJjmawnFTUUX6AEWSBzYYj1LV3CCtein+5a0u40\nB07uzwAELBnmpUuMFB1NgXFSYvBFnmegiT9ylgPNffV1EUdgSshfBQsRL18p\nn71kgdiIXlbQuO9H8q7pgcrgmIwkiFAYWgyPQIk3vNsRocnhhtLug7wamXmd\n2hXb8HE8mmrDNoqyYq5haSMlanleiOokvP/FM8ukDLv5SAuqbv0Pe/gr8xTn\nRl0NR7jGCfukZHXGYJikPxLpLuQB2Q10u5ZwP79Jkc7dYT4pj2jv+WyjTqkp\ne+XcXKWAyVyTmTM7WPqKQB4a2IzOnWtzfEzfABtT1pYaEYYlwEdQjFJBgKQ1\n9gIs\r\n=S+lz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDNGN/0JaZyCsKLwGZ/1mw3ydHRAK8RSUiyKWDlvpzuWQIgGHt4QZ8/MhFjmS9sQ0nFXNiSpDoSzX4zymeqfJr3nDA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.2-batch_1567405561160_0.21622894007892834"},"_hasShrinkwrap":false},"0.12.69-alpha.3-cascading":{"name":"teambition-sdk","version":"0.12.69-alpha.3-cascading","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.3-cascading","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-cqXAQ5mzJjtuvQNIhjTUT+Slja3OnyJ0pP0ASTHh1bDBPfrIt8jjfBnwTzUx2LgL+XybCBSGu+z0QayOGBNl6Q==","shasum":"97f161c847feefc9cd9970d5724703caa55ea6b4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.3-cascading.tgz","fileCount":437,"unpackedSize":931094,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdnF8XCRA9TVsSAnZWagAArsAP/38aQVLfnj/Sw5P1Jg2B\nhiqprbxMSCiC3Rus4kjRSrj2Lsc/7bVJvP4woVFwvf2HKKWPZ85WMxxS6gCd\nDKb35vxMI+At2KfCVM9QRDYhyXVB6GrM9MDcn5IA3hZ+A3kvJ8KNX+/+CO0d\n46Em//3dsipaZYnX3ja/vlbu0W1jeHjWLaGNQU97fp0o0hjP4FzeYr8Rllg9\nVI9GbEOm29OD9RQinEeTczUF2tqvrDDP90nWGNbrIjDKOu99CXWFA3wbhzFQ\nUdzi10I4tn9N85DR+JfgtCSTWoYACK37MzjoPyO98+e1faR7QDbXLVjaTRfC\nxvKZums+P3E+aJRs+fOdPM/K3DDgGGxo3Awg51cUQfMOBkZL6NZ8m22riYjO\nSVBvIIHCXrr/KB3rNQ+daTTz5aHJr10NrY+VhPsLKoG9Lb0Lyidqe/2xCRVV\nKlqei9AfNjrcYHxU8hmf7Js/hAGBYYu/lL6CZEyzJgNJ7JXVhZwZjktQNbLH\nThXTL/3z39Bi6KoqDXcpU9QPp4wJe+tiPwxZhe257+QdnjMTLRq3NstWlRcG\nOQp+t1HPBNMKGq1B3JT1kiOMkxDRUOSjN2cTNVpsH0YIixGRKf67XvuvNvCl\nzKkWneZMbNdllBaGxO5DlAbtmBdWy5A2zm4shE3zl7/uq8809aBbHIdegexE\nUqoa\r\n=R3le\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGCJzPAq5yBUWsVAXVlcOPfdOOY4S37jlV9753J3gVQoAiEArD3vOXLB1jfYGctbO5TwjQ8/UfTLesGZy4QOjCT/eO4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.3-cascading_1570529046607_0.7953381283798306"},"_hasShrinkwrap":false},"0.12.69-alpha.4-tapestry":{"name":"teambition-sdk","version":"0.12.69-alpha.4-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.4-tapestry","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-NSTFCiDo4GViE3YlbBODE/tnUOELyYl17liv5WaxNQa3ZcmzG7OMfWojHbnLf9PTEnE5LL2gigyqFpXeYt/wUw==","shasum":"89cf626cd4f0c4e8cfc954ab8627f4cbc54de39f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.4-tapestry.tgz","fileCount":437,"unpackedSize":931262,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdna4HCRA9TVsSAnZWagAAZocP/2C+uDsUrcJGYF3V3xdx\nZOBT4zKpYGEB4xc2UE8MaSc5NgwL/w46PMaRNSnQqWSsOs44cZoSzWxcq2SV\nVl4Ga2mWDpd1Q57Hm6TP17YvXvUBhKPhmGvbRpJRKjDMq69XK9Nyrnr++lMq\nehhCOLm7IapeE23Ep5MhkO40jJtTMmwfL1qO+dq7mihOuWPAkLWJHBtl7fIS\nNX8YMFJ3JgEXsmUr5epSUOPR1knWL6vURa0vOKWHMi9ay+GaTgWFG1R1S3D9\nd423fn+hVeTuNCRKeo1e3atncJKqMiOhhFWWVLG5Gy4iySEOfdA9zDXpeSFl\nqCgOnQ2ilVp6duo8+aBEkzFMayVCf5XxcvrpNGy2zPynaG90bBjikr0UVT4R\nN533ExigH30qhlS3JNm4ASj7h2wI4sVXmP6n1bkzevU4mMdRQ/c71GwiE3Ja\nd7Vicar9kvQA9rXWHg8iy0Gy0omIhBNyJfvGqj0587sN6zb243h8oiKpiyZC\nd5+MCty/G1Ts/IpCIL+INmh+etRsR0qUT8S1aO/xKU+wDkaBJbfMtKT+wwT+\nebpyau66OfLzqythHmsixTu2D+N+ZG6vf1INyp8b/117/sghQCfExqlNW78g\n9XQnCaY3vdrt1Q946oXBtxdpPVxSU2aMGomdOBwtq7FOGs0r3KUp4Pgaykme\nsmmP\r\n=JS4K\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAR0YfKer5MD8tVPMz5Gq6VtZF0Ph5zY4GwXY5O916ZuAiEA9kAdAiU03rMxbi39v/UuoUio4KJI0pqiI3hxRBvbZeE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.4-tapestry_1570614790764_0.585624333912492"},"_hasShrinkwrap":false},"0.12.69-alpha.5-projcustomview":{"name":"teambition-sdk","version":"0.12.69-alpha.5-projcustomview","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.5-projcustomview","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-j9DVuREdZFx2xHBAmVUt22UIpaKOaEOFJYjuV0I9lX80dX96STuoUvKJKmLiA95q9rBpi+sJGrejQxVNICRtNg==","shasum":"7ab7ce93790561002afd7da5022b8aa8ff6dff29","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.5-projcustomview.tgz","fileCount":437,"unpackedSize":932234,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdpZm9CRA9TVsSAnZWagAAtyIP/2LOPbnHECp9SbOg+w+m\nZ50STZaMafH9dvyKMhsUHe+55pC11107TC6bqy9LCLlrHc7A819Fj8AH6OHd\nuzATXB+gL/pzySdrKcYThUdkegOVmejJxJVa3/Wutw94knIDvEImvNbgCEdy\nwL83i8vc2tdiixQ4QCugRjHIWIQBwH9l4t2B+RouA+DCG2u8/H4FE5NlG7UF\nTn+BNt7WR/yrtqWDvzmXVoEhVGAjSUDhltyAPwkfDA/XpllhdSGQr6wq/zlt\neuyb5YuuX/TYzhI5MjmazVz5DEXcui+JNPyEUWvbLZMf4ZmUPLmvX32nUTcv\nmniURApvFs7YWzwufr1b1mdWcCMNsALscDu453O3dhV2ya297T57BFj/qJre\nNS3afbnelVy5XqlqrwghMDhlY9A0rRi5YNZYZBzD+1f3X2zJO6L6i4mlX1MG\nWa3Ht6WE2sJZXrxHrBtCRF9bqjQs/0qoA+KtsZ55PUBApl1xTNPVZUJO7bAz\nLc37Io0xPnPSrGygfbauF95tSV9vImn7QgeGfGHzJPhNINzNllvmN0db73Vz\nwl+Y/SFtoclcveCYdqyUbWi5qxZhxYIhrdUH7xA9o4SQSbXWYOstKujFzhQb\naJjhkZ7aPtTSARWG3xAi1SwZRr/zR5nHHu2zjfCoVk8PNopUxrfAs/5QJsjT\nXa+P\r\n=3+ez\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5rSu4/4aNXxZhmoGXf45SbX5vCw/a56rCSclM899KUgIhALgVvlciud7njdquplDVSbUcgx9T/zXEz8mxONQtIN6I"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.5-projcustomview_1571133884246_0.43706120553463035"},"_hasShrinkwrap":false},"0.12.69-alpha.6-cascading":{"name":"teambition-sdk","version":"0.12.69-alpha.6-cascading","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.6-cascading","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-eqSdr5WG+CPwFNNNDsvJNnPj+KUiOsfn2TmZAUm/FyAqWcDAeLSMnVTVnH3kZGjKgT2MVkSJF9qe7b8Ut4XR+Q==","shasum":"0aea456d7bbd03626c5305aa97b15155965a7ce0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.6-cascading.tgz","fileCount":437,"unpackedSize":931349,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdpv/wCRA9TVsSAnZWagAAWH4P/REhMcd4q8nbtrMPvH4o\nFZ3/o8faEJpgL3iLtml0uhw+BAtSNile1ncd6NHAmQn2IgjsovXrJ4QOY6SW\nJ1qr4kc8siOKWal8ubK2CJuic5envXS2XC5S8QUjPx7LSBReD9GG5/vQXGYB\nnws9VQSWIYy9tv9KSR/j89T3yaI+JmU08TK4otIJCXgpMQa2LtoWlQvC/ocE\nSVvOe30iGEY1TamsL3KsW2uvAm+0xLGqkvqOFsBbZy1j5N3PdM4XM3KaSKbn\nJPgXrecGYxwNGvaNa54DQB/1+r0JqrxAPRbSgmCPrGedOu53fhuVYBrF5rvp\n4WPPDMVPPYv4ZxbRsndITCwPrBzmCWaB5n/z8ZsV4UR+Ot2NEgiGAnpGHukp\n83uFLh5v1CNts019elXC35gGG6pBogS3PJQ1B+BcXE8OSqS9oNrJu4uP3h1V\n0Wi8C/YE5fRBa3rdekmwzpQYfhK8VucWYJumSZjrdB5fGJtKJPbYJactX15O\n4hfk/znvpXxoEzexobnYxPgAlAyqNPs2QoVPoQh08WBigIcl/2kDEtx9kmNA\nxu5YSAwzRqX+WZ52LvCSu2zg0VAP6Eo87RZjokf9tT8jMovlybOlpfb/U/N6\ny0SHFNYy9K9V32IVBHlFjr1Nxe8WwjUeJIZ3yXxzVRwZxHkibDvgN6TEm/Ut\nUZY6\r\n=vVgf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCELRfJy6xbxIUkOzXmKIiLe6NF2FaY1UtTDjfsbPO3cAIhAIAsdtQlmHZZcKw1IDR2HGa/dI7ssKyc9gJeOx8kf9QU"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.6-cascading_1571225583655_0.682011479006893"},"_hasShrinkwrap":false},"0.12.69-alpha.7-cascading":{"name":"teambition-sdk","version":"0.12.69-alpha.7-cascading","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.7-cascading","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-2C5MT9SMCo3LaTGoIb5raCMSy0+L4wVbio/F6maeHONbtHNBV7b5fbFNqpdECxNe+blcQW8crEcD13ULdIwo1g==","shasum":"a59918b9d3e702a35bd1cd1408c390a8e242786a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.7-cascading.tgz","fileCount":440,"unpackedSize":932038,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdpwgCCRA9TVsSAnZWagAAdWUP/1i9kVthiYdL8YXpiZJk\n48b1WkWKx5GwvDDMv9xHEWT1pYqLTpIHkfsfSRSeGhGKBYdNHFyxugNYAY/n\nf6K+eTxhRVwFagr8BaODWI7yaWFC3gfUz0IoVuzGwx3IE3Obx1kO4ogdQVsS\nEBbLg+a6Bv7ASBbriwJCp6DmmoZ4io+UWDLrJHOryAHjvqQnyGbxlJg1/KfM\nodHmowD8gMzqf8Mw8sQW7Y6cRctU5nIgXYZufYEOpVzhzmh4RX7Usbn3N7//\nDqzFTLyPx2n0uwLFiBrRKy1fywvqj7iPlYp7+N4uHcXtqrLuR6MinBBqpy16\ncmiTbEX+dzvERKuc7WxpG9CTgyXTHNZvw3fC06qC6ID9hm18BszAvgE3sTFb\njLIdN/rbOWdbZy2L1tLs9h9VxGAUKnDZXPdOAyWMoG+Rt6luA9ATTZu/S16l\nVmkdmENm1Uyahw6y3GRLCN0Mr7K/rWlnRFfkEIcWu+p9cEvVAkxS93aREHAF\n8wC4xSHNhr9EpYcR4xFW8ZU2grsa4kZXFFuHKSTqgV01cnksVW/rMFpi/9A4\n6pJuoZxM0RRmWUbBvr4rNVTOKmaI7GCO4sstTvkwnROX2tS3tKW61yiLgW7Z\nSyYkDej0vT65zSGIrLOihz+zgcsVj4qsHJOgwUKja7RzjHku9afNNOtBahIB\nN+Ld\r\n=tVAT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD5OTJTQmSmIA93007I2cBzVUIWP1Z0ddUCLfcelL2LBwIhAKnL75EC8sw5F0biK7lgBr1qgRyNuMNIbx7e2ZtJoVUZ"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.7-cascading_1571227649820_0.8381993527563907"},"_hasShrinkwrap":false},"0.12.69-alpha.8-cascading":{"name":"teambition-sdk","version":"0.12.69-alpha.8-cascading","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.8-cascading","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-2plIzEq3vwjs1VKCCERwSveVJsW+bVY8r5ksSqp8KpEAooMnNv3ioJ+kTmQ3J5aXynTtEEWaXfnX6vJxdREwQA==","shasum":"2ab3bf7d94d5d92240d63f0f3b44e46e6c4f2bcc","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.8-cascading.tgz","fileCount":440,"unpackedSize":932207,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdp/AfCRA9TVsSAnZWagAAvUkP/jvgNHBfQF1+fwUqHZdh\nFGsSE9oP8v8bzCE2/As7A6iN0n0m3gxpncz1BAMSCILkHfB8do6sAkN/dcB4\n2AD0mtiP+nEibUexCpid/GW8VExo7kt2duEY3sSpFMZB5/4pRKXGI865drNU\nNPgYuCkdIw4lftlnyGo9+eUkgXUwbgrxOUuGmVQ0Py4wt1osb4P+2o6BiSaa\nrl1Cir1RofNMv/E2qb3dhy5indUaPK10AFPEifGIqAUcaZl1g5rc4ZXLe9Yv\nt2kQ50EVSSj6/IH5iIuQnzGn4VRKXI+E8uf5LHo8+tmXFKXS3NBSsYCEe2eE\nXd5zutSnXBjWX0VxqJHKLwOm4QcvsppGlcFu03wil1JE1MBwRulBAQhlR7dD\nGcepvGKmnwME1HqzuWyJecUp+FYtM+sSpTjxIfGT06/cZQBOxM/rnqv1O0XB\nMFtsUXlDEyq9Bym0p2TNWmVd5MAM1aiV6QZQf1dlKCa/gpkZW0UvVO3HSmgs\nRtrkFeN/v7EG39D4UnxDL97nP5UjYtsse/zuMKDw4JL0P/XBhlvklBd5EuVO\nwtk5zXcuOezm3mL6zgcJuDHqYJ4may6naEKknWbfG9TE9LFaSfBR2LNplWGJ\nk9ZWWARpy6smmHWEkSKcvCQSU/q9FmJo49j7mGDy5WkZHnq6OUJERVm0HPlE\nd2Qt\r\n=zPlY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICz6lSEqRuUPB3hyG0V7x+HVBQe9zyJcIGPabhDw0x1SAiEAttUM/8a3exuw5q7rp3UXBW2jHoupH5k9WLMlj8y01E4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.8-cascading_1571287070174_0.9462556740576109"},"_hasShrinkwrap":false},"0.12.69-alpha.9-perms":{"name":"teambition-sdk","version":"0.12.69-alpha.9-perms","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.9-perms","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-rd9VoQ0XDimOzEzXQSzxIPBPw5EaPoBCSLeu9/Y1Luw6Ilt3cF/YQr+llYM4/XHCFmBV0OBbwqiakkUAGTk4TA==","shasum":"961f8bbfed0c3e45734b1bd5056ab22a41b81b2c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.9-perms.tgz","fileCount":449,"unpackedSize":938469,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdqAmYCRA9TVsSAnZWagAA9wIP/Rmlil3w72Dm6xVz/Y19\n4I2R+rUydLFgxcKyq3BJsU/whUfFaFmSY6gyv6Ngu58q6tAEtEGkCEbYk3hs\nQNEOt/p1nmfN7qHBQSV5HpEUWwKepznMnhWDS+Atbu+mymSDeWig8f8quK6V\nauDSHGvyWZCgsqtySVZIubNrp8f9m2jb8XnSZXmRQsogxo+q6n2LCelkflvy\nvKieOwIqGC2Tn5VL5Unx9otDhrXLllGcFZN5vISJFS9KUwGEuDLNklppi4xj\nFzEV8aGu7ay6YEXp2a7ocrJRVqckASQeWUIpv5C6Mh2MP1J7oBVh82Mt/Hjg\n+R37uZoR+shNzdqi11uQFkUh4++0tXm1R33lyp7IwAuB8+5D0PTsjA3Ry+UV\nc10zqarlkOEKUoasfsB+IAsuXz1HFylV0NDu3H5LuK5I/wVDxVa64dXx7F8J\nYsdfCY+R76uGnRZQKrqhxg1IVi0URffhaEo4/RacD9jXsa6Hf+i9MWI8Dn4l\nCq63sXerYc0styWV5Rymb7iJ/aTP8gXl3vCAPVTZLxZZX1LJlNiX2H8ZvvCU\nJtoxYlFihdeHXH/vuYOzuu73soI50sr4dEKyzu7zDqZAh8YB4z+kPPEdyqZr\nbMHO5f9irtXk8D50goC1mvLGp0cJnd1pICG/9iqT82eT95IKIJM3T6KB79YD\ncxLp\r\n=D5nZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB3sORxugq8mVRuajTBxFN2YbKLu5dzyXX6rfx6/scfOAiEAsUKvO17HB/tldENBZwkqixfWi/DWZSLWS02cWF16hOA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.9-perms_1571293591316_0.186667002907148"},"_hasShrinkwrap":false},"0.12.69-alpha.10-cascading":{"name":"teambition-sdk","version":"0.12.69-alpha.10-cascading","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.10-cascading","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-gIdHsqHrUJdzCUaLfFP1Uvk8hXU0PyF+l9JUz/YnokUN3LI9rQq3p7OvIggS1dNOhiMsBp2DS3NUWmHb2mNHNQ==","shasum":"bc514e85d10bbc3314df193ed9310850ee993b6c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.10-cascading.tgz","fileCount":440,"unpackedSize":932435,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdqIRECRA9TVsSAnZWagAA2aYP/3HTfIcdw3JoNFb2FKp/\nKDeaCsf4wtMl2363/fqYZNIMPlM3fX0r9/8nd8dhxExS5hXzpqUeogpnPvCr\nshpOqNNE1ydewPlpw08bLJuXNA6ji2gqr0nVE5n6U45WR5orFMmYjuDGbW7r\nEuXEJIEuHH7qjY/geeHLq3e+ImMKeZt7tQxPw34ZRPhq/FZf70WZIKpgwUJE\nUQ9gZJbURRk7Unb+cCe6bJmtqQv++tpg/AhplpPDwBxGYO/sWrVyuACDrGys\nqI2y9XLTflMzxdz8ugWiO6NHwZsG72M8gykyY5w+J1iW45i7YdMYT/rhy5Xb\nyzLpKpAQ6pZQzzYoQJIIgQjbGSb4tWWMtAsL/QmP1BP42nVwf4Lvg9gZxUWG\n/hEluB5t5dP/Mb+kC2xcOL7ieRfhF3viYlyPNQIAN6Lo781J2dZmIKnXuvQl\nGGQs9tw7T2UlLNY0cfWjDu7IhpHjYwKhii7+CI53+JekJ4hRKgvZpOqzk0mn\nX3MI6z7Fc9lQmKyMnnb7D1PrloI0+V9z6uxDEcu92n+84kagFI7b+7WSMCre\n/lTdGnnhfcWq483C1P7AvXqnEcXY0nPfc4/D1TS19A79VxXtvHXLR5Vln0SE\nKui6xCK4CA8MJTyo56puRI6oCoVqjFarsEW+6hUgKAUOErxNaj82YHf+M7+z\nBo22\r\n=m0tG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDI+9Y4E9pr0KCZOTbS6AvBeN2+r8hww7dfeJyAgWAGxQIhAJglZH0AVGXDiH65cBJJMsZTWigOUo+60h7E+/4svQwN"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.10-cascading_1571324995381_0.4410917252615305"},"_hasShrinkwrap":false},"0.12.69-alpha.11-tagids":{"name":"teambition-sdk","version":"0.12.69-alpha.11-tagids","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.11-tagids","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-o+qhDmmyokAiQ5pbnsQXJ4IozvUN48q8+93Mi5dB6atYKbvf97UALd7zmLqPe10dZv8uCqaHIyTTvIu/5M5HMA==","shasum":"99c0b72506ac9796a89cb0e9272bfd24dc70d954","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.11-tagids.tgz","fileCount":437,"unpackedSize":931283,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdqYCsCRA9TVsSAnZWagAAZrwP/RWW7a79WdodOu/Kq0Xb\nBhThtxqHA3t7nftaAtOtX70UIJwD+YIGzTHrmeGDbA1C1OXyPJBKjAbG7zP6\n8907Dnf3PY09aNs31OldH8Iif1AzIBEoBLLCwDNdBq7a81s01zfPTiZlzmzG\ntKu8orB+Uvf7IGEa7ntPYZI2gtc3WqcQX1Jv9mwg6kzPJSvj0UauQzxMjsiq\n1QNZfqJFL/MVvAZCX1lHWBa0NIvJnMTxuvGJn4YmIQZfaD4odQjlHEkvKfg2\nB06OFIj0IeINefmBPGAsrhlyyJP0Hsg/bXOHxPTfkS3QAUDbufIbuUBrhY3A\n+5SUc5IhH1J4Fm4GX7p11lUpTqiSBArog5cE8trwoeCn0v/xTPZo8FN3kUnw\nXsr3GjCEobNslEuvMrJIbrAQuJPUF7LwQMusH9O/wResl82rd/y1Qytx9rgZ\noT0Go4Hb/AzLjpb8Bc363ZglH8L6+cpLKb1VKFpxPUEfhNKP3HOfwgZT291P\ne0+/Sw25q+gV16x43GEmLqPzNuMOcoQyDX06x+9SksWlRV2K/7+C6EUJwHN7\ngStbSt3ywAd0hZhlWUxnfymdQmJkZ6vY/bZCk4LbsC68rJeIChdlMa6NT3pr\nH0fdkO2RvtuVdX825/yvSjz5ZAltprvKCBLLz/+HZfYC2AR/phecSzsapk85\nf244\r\n=9Gem\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICbTMMwFgXwQ652LKeIWh4SmFaINys9ytOuN1MCqhmUYAiBzV9GV7cq5q9PbgcrXeJC7Q9YnNLfO+EHlh2hxVqwhLA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"tb-web","email":"web@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.11-tagids_1571389611714_0.3985564082811186"},"_hasShrinkwrap":false},"0.12.69-alpha.11-cascading":{"name":"teambition-sdk","version":"0.12.69-alpha.11-cascading","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.69-alpha.11-cascading","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-xibY2NCHdFrwEvZEpiIJIbincWZDMji6RKEPiMN5ioA4Y6Ve532vC0d04GjfYWYa6TuzaIPuuGQBj36tlXe7Eg==","shasum":"1e345f653139c68e8ea7f63cd443fa62da293b97","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69-alpha.11-cascading.tgz","fileCount":440,"unpackedSize":931981,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdrnuxCRA9TVsSAnZWagAASF4P/AnmvXs8CwG4EfwGO/ua\nowDkpoRtzMcDu4BoxMAyfXcpsFT5tZnArSZ1UqwjU4Oa1h9jXaNVWhZF8rQ1\nqysP5Wi8Y66f1Fg9XmzRdMzjB7Xq3QpNMo67QNwlaNaP/IlFkva/JQyX682U\nuwDpZ1ln7N5rOzo8rpNLSaKtMhp+RC43ySq7nSABYClZn6NFq3w27NG5yUdk\nAiUE+DwYgVArZh1r3I/ZVt+Lz4h/ScjBy6kMBh5TDalN8J6fKDAVhwtOvMas\n9Zy0Ri0heQyj4DG2TjaNyndhcJjejP9VXzaRQy4exwYgHssn5sUsa3Lz8syP\nz5pjfKiYXfj1lQYDfU+HhsR8J0fMB3UGdVf2Dc0D/hdbWrWWmnVViA5UHfvX\njuvabVn+pBOSCtppuZO1siDcpMC5QIVDdHcpgYsN/qSaAIf7Mq/D3lu7kbOn\npxCwNVOOAgbEw3/cDKuLKzqAui7LZRYmQ0CD7xowFGqs0BcAPca3SJE9QTSW\ncnSfp/T2IX1YNDRCRNfZyBgEOZD6fXEZ9qFEwUGOl5VEuEDcs14Tos5G+e7K\nb9WY45Jgk/OuGfNKI+6FMwf2ph/tthg7N+v5w5HWmG7MZtW1jOOOGmR5vKAd\nn+ikVYKNZRDut05m7+lUEx+lGlwGOf1lfT+YZz9Jx93sSYLT7M0tPbYdm6e8\nzq8U\r\n=s/rn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICKwzpSzOfOvk+cDQuG+7mWZg9b1GActfFoqtAOcYw6sAiB1aV/y+3uZtID6eWwz5JARvfvQWMHLRkhTBBePSsqCtQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69-alpha.11-cascading_1571716016496_0.4535719295868783"},"_hasShrinkwrap":false},"0.12.69":{"name":"teambition-sdk","version":"0.12.69","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.69","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-KFlbkshs+6wx01v27RdFsis2BJZj2abip//qycNndcYVpHZmrudJpUjdxsJqMl7oNjxt4dUJ6p/xdYJparA6qw==","shasum":"f2e960a0cc647ad0ad338d90b2f25cb3caef75c0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.69.tgz","fileCount":437,"unpackedSize":931245,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdr8r2CRA9TVsSAnZWagAALUUP/j9S0MoXi7o7tjdfxY+x\ngE+qQ/jhsvMoPJsxjd0/9VFEQprJjluxZ/Jzr80sTlPDhPlNMHBvaY9RwvkZ\nR1E1MvyWZ7XSkS5wARGIAk17CNIxmwZZ9QKEvSGkddHT/pskibWja/dpNNbB\nlVTEHxUJ6mVxtjfPYWcN5anKLmQ37/ajwQi8/Mfh/oqrr68LRZlSJz5dHDOV\nl5J8sQAyBBXd2PA+WUPG91rYf4YMnedB0GUMi2n30mxL98DJzXFsohHlcIKB\n0aUrgh7rLC7Vjryf3qSpHKCexans9SU8fK0hUYtmuhUdZC4NiNu/1Oe3SbK1\nMEGrR0Hc41xPtln3Nv1jGELni1XeRDcoX74y/3fDQqT2Z8p1uzqKwQXeRydw\n+WCMuS009+qicbF7jREBFB5isB62F+DQogNH/FQBTdOvNDmlwXsAUftwlla/\nKgObuaF+vcd5ml3JifN43+j4OX6oSaLcih1kUMRXRW5Q2t8e/dGAFPpDA6Ql\nZ1EP7TXyVhmZ2/q1KV+daol+q4lKSUNp9sK+TSDBIvFsKmjroEC+1ql3b41E\nfgjEgIgkDCfxXpOdibg1Qjl8T7BI6lotJSC71aKNaQLDp+qkGmZhNAv53bda\n8iyJdLi8yoxSKrfgBVKt+Rl0GpV05oFQ/rUNn+Gr5DAdMp00gII0l1dWARQT\nIA4n\r\n=qEmo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCfmardGQ+fzuDjrFtAEnrk8VIzt0m3Yvdmgu3ZZa9zAgIhALoODx4u5S/m66PpFC7Rue1PqiZAxIdsuudkGDz+E+eD"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.69_1571801845466_0.8395446299891993"},"_hasShrinkwrap":false},"0.12.70-alpha.0-cascading":{"name":"teambition-sdk","version":"0.12.70-alpha.0-cascading","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.70-alpha.0-cascading","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-u3CfnYeYrOBcl4Xvtfl/G3f9U2cxpgkHEq+IvRWj94rTQ+/tAbeDxqh0fUy8SDztiwEpR6Cg7VLyUuxWpA08vQ==","shasum":"f160fb68887f1e0db7175da775b9cba4ae2ce85a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.70-alpha.0-cascading.tgz","fileCount":440,"unpackedSize":932823,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdr+qXCRA9TVsSAnZWagAAOwIP/jANtAbSHT5XMbRJPfKc\nTh/+X5bViQ16+d2bKHxYeyWJhJuBGNg9NsoIf+TWsWR71w1Gq6KIFCssldiJ\nnyBFHmF9mUNrC5ia8c7pnkNCAnf9LR1kTnyNHJygSmGsoMVgRwxys4o2AP8q\nJy7189fZ89flK9lGGn/p1BSiBWC2cKI4H97Buc9K1WRnbFjXHAUA1vXF+cf0\nd+6k8x7Sl4vzmaDZId5srUtCiChhPmgc6e2LXIcUauRqN2YieRNYIj4eix1T\nEVj7rZcjwzVymb/HvTGpbsMEnIxbfbWvjsxi5euXVKqkyruP6itqwXnaefJo\n5CTe1yh1PEKA0T0GE1J/jVZBxgVPnKlsH9jP7yG5GpltzqcZi21cvxLfL9Vx\ntjc4XQYc/slWLZqRa/RwAlelehunHgGpqSQBrucf3sRnaZq5PItBMwTGw+0z\nnKDE53PArnp5gZg5nTh1J0fzAI9y9VkIEaI2hTUduOMi8TocmOEPBU/4CwGi\ng/A0MdLhttqxlD9a0clqig7wsX7NEuqzBO08mUetVu9+1M38IYeTsJciHCTM\nysGasnGc/K+A4M117eP/drFtr3LkiyPtwJ6a4UTdcAFAnLMPhITHtN22ult5\nYAZE1B4RJZSwOjttJhh/bEI7aU1G3UWVznpMFx162Gz3i0m8I/cd24YmvLz4\nnZYW\r\n=hEJO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD26D2Hr8tPwZCyte0l8Lqyk+TUQTVY3gqYpBMsIeLc5QIgOerq/GRL0WKpyNkMlYaIPzqH9wKiOKISER7mbYf0cmw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.70-alpha.0-cascading_1571809943130_0.202041622708949"},"_hasShrinkwrap":false},"0.12.70-alpha.1-projcustomview":{"name":"teambition-sdk","version":"0.12.70-alpha.1-projcustomview","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.70-alpha.1-projcustomview","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-rFmclgZ56pigOvUd8JZAsEbRgmH7eDnkDgOeK2Ue7kE2DP7m9dGawbua0pgxqztIzNdDYPQRAxp0rnU3snLyeA==","shasum":"2d4a02d7dacd1203818ceeb2da2f02163ce51d94","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.70-alpha.1-projcustomview.tgz","fileCount":437,"unpackedSize":932425,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdsA8NCRA9TVsSAnZWagAAivUP/Ay/cNbUbkGarguw4Kyo\n1zg049iltBt01Wm9f84guphGVn/zomyLEqyhVfT3NeiYFJPA/6lObAguMhE+\nWfJOgOEcQLkRnrC8BDpRXQoGYL61RCMLwpOj2FFrhbx8sCTzB+25t2/964t9\nobn7vNwFrouwQvhoV1fpvFP08e7v/39Uh04gkDAz4kw57ZDdsYI7E0I8kXhR\nQR/wbSzSoQxLFF4K2z2K/gF5UaNbgI6qYAZL7RG9vpN4+e4KneQC794oO3GF\nRG7AwCTDnB/Gx1M+8r+azqmoQ+9JiaOWVGwFLTSaH+w5eNhQDRMiTiOSjajz\nkjpy0BbAOMY2bHJ6tZy8cDrQTMBjeMNYBbZTcI2FkZlX6TEUWwSY7+FhtAy8\nvW1iNqhV+f8vYkDEo05q6X1Uhi7O7k1Clv37e7mUPDzL08t6c+tV0/x+Stu5\nnRod+C7okT9MnhW1YRQoSN15Z8r367mZJGqqN+bU6q8GlkvZdPPWr1NGekMU\nb5hb3wEKF2yAs4l5re0ahc/D5HqUaP6xMUey/X9UvVHRNEjouFqBeUl5Aaez\nc6ay/1KA5bA3DMmUozV7qSzFVT3QA/FgdQETjtd9rLNc1tFgMaP+IoCt9k+z\n6GAc0Kw1V6aWV+3rTy2Pvgh+QrztqSyu0LPDL4WHgxFpzAuYqmheNq6Ruoia\npql/\r\n=H+KK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC3ffuj8qdk3aBB4Dqat0Cdx1r1kDAGNzUF6+qqm6FxAgIhAIxQ8XpPEu9DxatZQG/GzU3mbNod/YDZxrdGDqnILkgm"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.70-alpha.1-projcustomview_1571819276911_0.6855173714438028"},"_hasShrinkwrap":false},"0.12.70-alpha.2-robotactivity":{"name":"teambition-sdk","version":"0.12.70-alpha.2-robotactivity","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.70-alpha.2-robotactivity","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-JpeBcNfi+nH+o1HqNaWLZ7BkAXxPT/b48fVlRe37UgIQjzV/SoHv6SKS9TThhc0UOX4GNp/Mi4fVcDzpgWN19Q==","shasum":"11aa533a4525cf81833e9b13c8c360bf966441f5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.70-alpha.2-robotactivity.tgz","fileCount":437,"unpackedSize":931323,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdsQxyCRA9TVsSAnZWagAA4h8QAI1jogAwL0jqhiAMOTM7\nZwzOCVyXtygWtBFnyMBojRv3VCZeCKdMq+0sZ725tWtKe7fnsk3jp9uLPJUH\nHau2o84wJ94JU7+092DndriMenSJ5dllt2+u1kTdjLrriG49Awk9QPqeaBoD\n5fzQXR4CQHjGmKL4JoUotUpIZ6R2oirm/jyx6B+Jiidvi4ajBQjkx0u5326o\nhmL/1DtxxfhLX2Lwg7IO6s6Nswnb2ArByolZHvx6fR1tyiYTC3kJ6HPKYHR3\nSG0/lAJbKh7XrZlQvaLjLBTT0PCl7u8ciwqbNsm6GXEsUSfW4ucPeinl1qPp\nqdbHpDH8OJNF+frRPESn0ufKw9wlUDyBcKq9AH5lOCY/mjcKieYx0/y0q7JY\nmqv/2UKLpob01IvPWYmEyvaRGXOpw/88JaGd/9eCjTXRsXdZRVzalXOwSi2K\n45vGJ4zzwZmxMw6tYJlL0uqPOZvnWEhtYXIfD9XJHNiSGmcElghXLUsQITdl\nYMRnzFZ9mSLkUNpw4IrmVr+zxk/I9nIcHYGyUa5ueMAqgZ0RQkL8sdd66iWv\nJtRWF5oIoIJP5lxVwMZCLzF0sNCM7jPU/U1cyiPETCtjGKgCei6FedTiluD6\nG+FpLhItKkhBOFY50c6jcWG4ioba6suHUPRrKjcEIQ+Roz3ek3VyU94TqW70\ncn3v\r\n=uvk1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBNeZQvKSz8TCQjo8aFYJ5kCBZH+Gsq4V4a5ZeE8FK88AiBL0f5EEyeTcNXGfxWbtOJcvjbcSaIZzGYN2RNhN/8+Cg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.70-alpha.2-robotactivity_1571884146044_0.4777740884662307"},"_hasShrinkwrap":false},"0.12.70-alpha.3-batch":{"name":"teambition-sdk","version":"0.12.70-alpha.3-batch","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.70-alpha.3-batch","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-kMGKfo5C3UhwI7UOWjrn57myWMZcvmhta50pFk7qlvOYSYUK/9naNP9T5hQ/pgmvgTvIcXb5D/88Rai58YnDpw==","shasum":"1562b0f13e6ce68a4abcf602c5a1544cf0c7b77a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.70-alpha.3-batch.tgz","fileCount":440,"unpackedSize":957934,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdsSBkCRA9TVsSAnZWagAAyB8P/3FYbdQUIPQAgiHp7BlG\n7NhZ2Kh9yzB3etbe6/AmAD6/PhRXco+MlHXL+a+kWzZ7x04bD1N2fZnY1at9\nx3o/OLPx3znLgSWxlsbE1sLI6meAfx+bHbMUhjydI3UUOGTmz9D1ZDbPipnL\ntYO+Z2vyNJluFFGBBFjlffP80G2yn6IBQM5uva3jZHWc/d47xidmfKj7YVu5\nqhXgJw7Lc6hC/L4M1iMttb55+6O9+IJmAltnC7uENfUNJNkB8ZfoxSky/poY\neGFMXp6bpuW6yj0pMzooZS3XGpYpOUNklNuOjDZcfK+O1QvaJDXg9I7k9HKa\nrhq0FiVCnSJz+eI9xBOlb+Cj6GoKNYMbbP3UweqJ24znmTnat4SUrlrvqRL/\nTvrnGE3UMZS0+6+35u5HsbGn0EF4AfK2a9VlaxvlF2aiEKyVwD3/mL3GWDSC\nNYndKOf+ZlYkrdy5fzMSME4Rt9J7mArPwL1oWHC2VPvobIpiCH9T891I5e+k\n+T0AEoStCzfcZZdtISyHR8w7ymRKuKNOy9k9UTBmGxLHN4FM/EQtefwGbENB\nVftTz79/CotR7Lzb1Z7l7vF/n2TFXlLXBX0FBY2jm+rS90/WhYaicCbQA7Og\nX+MW6jdGXID4y84dkdAWFrChbDsPkZuxLAJ/beApuRo3nZHX4pDlFfvAcKsy\n6Dyp\r\n=L66w\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEDxv/UZq6bfFmA6Mho8MrUKqdt8QeFNSpayOkOzzxs9AiEA+mFKRyBzjpBZKr90RspIBAjsz8Id4Bbdyh1DjXQwYHM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.70-alpha.3-batch_1571889252224_0.25468791048009565"},"_hasShrinkwrap":false},"0.12.70-alpha.4-tagids":{"name":"teambition-sdk","version":"0.12.70-alpha.4-tagids","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.70-alpha.4-tagids","_nodeVersion":"10.16.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-kGMhusIRREfw8irgHo7C41FuaQcsqlJdlQdBpud0OchSUCmJKBdiuOhz/sWYI20pra1v0W4anP5CosupksNSzQ==","shasum":"456c4ff55f4c049f6fb718c442e53ba004de82b4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.70-alpha.4-tagids.tgz","fileCount":437,"unpackedSize":931479,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdsSL5CRA9TVsSAnZWagAAc4wQAI63LBAp5lRh9mCpQx4p\nP66HkaoblCoRhmFNYbxM7M9V+2MmBQo04g5n2M4Qmte/XLGUhcSeShqv3PcG\nHATi6Xt736hgnz5o9i9ZydqsFl/DsRGpDAYM2ny45mExc/SezrlU6RIAgyHm\np/rAL2f3bghc2HRnS49A4bo1M1lFWc4qyA88CUGCMlwwGw6iw4Yd1nMEkFGl\nrKDZ7u0W2tRfuWUAbTTKEUnc6PpjTBGFcV30b8OYxtJ5HqB7BPhmyCbW5u9u\nOZR4LFbNgbotWNO26JHmesRiHk0Ul9FRDXtqqW4EFdzBQg1WEB4KsNa22ae7\nqvrRRERgIytMJa33h4bU/7KeYRGfuOW//m0EZ0nATVmx21Oqr5acbF8o9NKp\nHIf5hTP1PeaiGK4LxD7SBiyIJc+3EJaIPFpMy/mSvTQ9kVEfdN2Eoj1Bckit\n8xXZLySY3/JO7iU4ubOLtmiYWc7gk4iaRXkYRgyca1u9gIs1WetUf7URfLtY\nUoDp9oO1N6eADadooO2woXY7l7AXryrKeO4I5Y9txAgAytXVJP/uhtCwDBPi\n+XoTy/mpKXi4CTvESnvPajy/K4wFuRdS0148g/wFS+uKfosYTzNyYjWvX3QJ\nIB341BLfFleLliZQbM6+Y+sFaIQjbXydUMStb/THc4o2DkLA7PmCS2wLIEGo\nhJlS\r\n=zvhC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGG/w9QYxDoIIdWnGxnhb+HE35WtBA5CKZ4l7ERZ8/IHAiEA0KzmGlsg3DMliUerIMKefiVYU/qa69GNdQQnjjZ+tpw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"tb-web","email":"web@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.70-alpha.4-tagids_1571889912985_0.38502871848079256"},"_hasShrinkwrap":false},"0.12.70-alpha.5-projcustomview":{"name":"teambition-sdk","version":"0.12.70-alpha.5-projcustomview","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.70-alpha.5-projcustomview","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-ofGXjWRx3fOTVqxA5Zaoh5qCQ58B3HSFfHXDB+/7C35k9gyTFDH7bCRabqvJfNT+eTZ84PjGE7CNjgkhxtKVRg==","shasum":"a4e8af673da3e6f76cfc11a3cb4170c3c9ea647a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.70-alpha.5-projcustomview.tgz","fileCount":455,"unpackedSize":969302,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdtpoZCRA9TVsSAnZWagAADIwQAKF+fQxp3+J0pUN1sv2z\nNqvPblcKiRpca40qHzPwViU78zEUtywxyzU/7RR0Dx5vlSsKKkhMp6dRdFQp\n/IsfwpZVeo1+v6jlxBskKsgeK1PGWdR+4PAIYXeVPiYip/dsKYOzeQ5uofdi\n8fFmO0o88xk9QtlKMnWTuKySXxnNNY3SnNUaRZOAbQZiRw73mXBY9Zcf0qDS\npBhHytus6DaeymNG/kQ92avzvLI5k/Y5TfUfaDKhHcUdGFYey9S8oNabiWPH\nmAYRpu6f+ayPYZk5lmP3BVsBzrLeE+rHlIUw0FLESWhrRiq0ZuJ+pVTU7Gn8\nn99FpH2CmUFAa0xIIOmbFAZIcJifRI8HoGPIr+GbuT9+e6PkhIr1KcTnuKQ0\nKBcg52eGwR0kYY9jNlJwD2pHTYv0lgP5hNRfTi8x9gkUvGjM5jqs6Gy3Mo7c\nqcVvQNR2k3ttKNpHByyjiCfq14bO3cW/31Pc6AttwL36wU75dRvcgij8fwVM\nvGMh2SDuG1KzGZsYbIjyAiLdmuaTXiVoeDgkOjVo/VICLE30YG6Tcv42vgWl\nKtHfmC5h8u8NWFS9QbwFahOcUuWSMrIwGlV0Pdv916PcR5IjzHbPEsA/1u0b\nnnl7KXqZotREvemdgr7dtY3omfpl7MdpKbLR+OHwzUfihCOZ0M0dOvtYUkLP\nWWAZ\r\n=dyWD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE1XXq0Yy0UhOi+09WVmmORTEutIUqakqpe7yoWKp5iHAiEAu2Bf3o063OtXIjdEzjkVELdMF26zZ9hZCdAfdnHl2pQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.70-alpha.5-projcustomview_1572248088795_0.27303681302801275"},"_hasShrinkwrap":false},"0.12.70-alpha.6-customviewoptions":{"name":"teambition-sdk","version":"0.12.70-alpha.6-customviewoptions","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.70-alpha.6-customviewoptions","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-+x3juikD0AVdbRtvB613HlvfL40TQ7RDvXRD3JLzBFy+Yt5XrhUGFXUVGhDUNLB2GdYcwPagBRdRimTKTkfU5w==","shasum":"6154a0991121de46632a15672185980ff06a811a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.70-alpha.6-customviewoptions.tgz","fileCount":437,"unpackedSize":931386,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdtqR4CRA9TVsSAnZWagAAQ8wP/3bPtYRdvMtnNRiYKdg/\nF47cspmdBPAqd7rypBaQFRER8fsNl2BxESlyjLpTxU4fXZxwDbbz6pK+UTfH\npx1XlcqDMrT3mPgsb0uc8DqbR8vs7xiIbvK4+XIMAZCgI6tGA1KgP6phIj6v\nGHz9E5/RmYBRT22uKZypOt2AtuPia1nVSiEVb/QaRecHynd60Yw8LiuBlTyK\nIiUSB75Og9CH4GKLBvzZH5oKU8fOuSIDffmMhpVxs4fOAx/UaduOZPD8dDrc\n2tTGz2M9mvrYmXREgKUUo7gJQsgAqA7twYSj2YRxNIQ8PL4QVK1fAuGiz18w\nDV2jKfmDyYKS9Lmrk8EHC1vzpCV7r5nJUxHESkq6pwIi9n4gGVNY8M9EiUrn\nByrLCwWAKDYT1kgIUKW3xhBQuEjdKwd9M6/+ZyBhXBuj1ajNTEezAnyd7S1/\nWU+Ha4qXr2/qp7i4tLBNOY98XwWBHzO43Mt3jJ1pgFCnMrVYLQsqbdD4/RPJ\nbg+vhVyM8I8Z0LpYUFOsfvLawtyXIkJu4m9WWoBL4eDOnfFO2/b8hTyus0yc\nUS2K5CbQjDh28Uy+VDhOVw7ycN4n6iTDwL43mdy7EeEmKLLptsIIpfmy9lJB\nAOTgoki19cOyeDnOF23qK0tOGbXv4RkOZ/D4/awlSnVJi9bC/Z3yz4NxAO8f\nev6u\r\n=Atqe\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDKQnogZ0WVQp/WUx99j0IJ87vu1ZxPigVQP8JBaCH5vAiEA0pwCF/OBGojSSXTirmAr+XAKkse8AoYnQ3VUH6uxrao="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.70-alpha.6-customviewoptions_1572250744320_0.22638389742218012"},"_hasShrinkwrap":false},"0.12.70-alpha.7-customview":{"name":"teambition-sdk","version":"0.12.70-alpha.7-customview","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.70-alpha.7-customview","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-uSGzVQ17CGUbtvolzcoaiqQh1d8pA6IYE4h17f5RUJZ3gcYDB8sTFKIDsrEF8NsV0M99HruzZ5i6VzYyl0ZaoA==","shasum":"6d273a2d3e8df7fd9b4fff08e4bbc5a0e098dfb8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.70-alpha.7-customview.tgz","fileCount":455,"unpackedSize":969413,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdtqUfCRA9TVsSAnZWagAAIysP/30ABOvsBuh+k713Rg13\nfiX/auf2A+cGBRwIbFwC63e4/KkswHLeJ59L1g5ZdI7UUB3P9FWDiC/q6aMa\nVzE8DboZsEp8YvX45SXJBDR4HISkotVa2wHTpXnzKyG2Y+Ntu36jS3vp824t\n5QERKx/ENMY3FIoq/ikEaNfhRiPqAUVY3nz/WGp4Oea1xQuQGtsaTqXDPpcJ\nsDgTE89V/f9jcOAiZB8zvSNtt3lLJQ22/gwl4+Hyb7IJEiDBq8hH1Ui1BPf+\nfFIdi5FLRUD7m6C4rEFO2o/MRt49nejRUNkbTQWX2aquyT5E0KASm75yeBLt\nYc6ordGewqOFQ1Wn6SB3eq9fKC0duRU0BErI3AcSURb6iE1ycSriv9Efgx+n\nbDn7FBWlYKqxsUTb5D6PpsCloqpyAXEv0DlR4qTi6kQj/5SbHKb46mkLgG0O\nPCO+MCmqhOJOGuyi28fMSNiYpptYcfovSezmNI9lsI296MpdKw8BOkCst3ZX\nMkXh7oHLqQME4hymNcLFKC2WQYZeFitrI/wznWay590W4PkuLmqCwkA5eYBF\nI0ihwZx2xKQP9eOrcAcDRhQtywWQ/XCvIL80N5sh0a+qnLa2VLS03QDHfc4/\nJiRoEiWjO9VwH5YJNgZnNlRnRrdhOQRU1EvYvsxb9ha6UALWkjvMveQ05c+L\ndwBq\r\n=AoD5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICJAi7g6uQoghyQyHu8pW5WbSOiQoaqICta3Mytv3MGZAiAc7uXT8IGypkgUBoxKNjG9qhQeqwi1M4YA6qLhu9+4fA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.70-alpha.7-customview_1572250911499_0.15744455860039275"},"_hasShrinkwrap":false},"0.12.70-alpha.8-projcustomview":{"name":"teambition-sdk","version":"0.12.70-alpha.8-projcustomview","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.70-alpha.8-projcustomview","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-zs6yP0+F3CbnWTQiQbmCzlEmrufWUWRzhtKLr6UQJ3nCVfxYDaZjBJk40wbOcI8gR/3N7SOa28pJSpvPZm8fuw==","shasum":"d6211b77212fc5d608671ad46100872766f882e2","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.70-alpha.8-projcustomview.tgz","fileCount":437,"unpackedSize":933071,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdtsAjCRA9TVsSAnZWagAAbkMP/RphKj3SMp99LOE1Vp7l\nNpNs/jSrCDYg/z1ZMTtVaWEygtcjjC8QFq/bOV0oVunbbvR2bL2s71KpyYNs\nid67iO3VsbvU0wirvcZhqiFb3IPgK4X6MES0aZJQrJF9lezbdt4dsaH3gJ2q\nn4ysHl8wz5yce9DDoExJTUXho4FfJqpdk2RLTaVbWLxB6xvYzYKl+SSkb6qE\nTuBUf+ttTEKv5YmLU2HCt2pGDgQVBbIzQ2dciaYwFH6HCZVWkZjlfVsChMn8\nyyNLuEOKrayH48GcOG5jtCYIHuTViggM17haoRJmSGTD4826ub2mIDPmch+v\nyij4psQJhpl+ScfHl+QjKQ2gsZSNq56oB+s1L6CLFtD6n0CaSdoEXDOXPTcu\nmIo2FtH7LfR0DauBKdhhQEWqXGJFPit7nLEGOk7eaBhOnhWBUAscmksNLkWr\nx7ly8gS6xKSbi0vtZACpu8QDmO/JnVoO6Gvxo4o4WJwZ3pSHRnkykhON3+eJ\n76zt7tV2sW1gVSYEn3rJAn7mZ62tC0FXgr5nOLoIamvLdjuGHbLLlb6LtTdJ\nXICSs+FwlhldVAv/6x7b9al6LC/QXyn84rXeOKXTDgt/VrfH03Dg6uTtTZGk\nKhwvedKc6SqCDKNZdlu0KfvOu3s08wNN9zwHt4VR7XoBeDffiEPCMiBzNKtT\nI5+H\r\n=R+x8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHbDNmtqdDbJScrTG17FCGR+BcL26NhQpl+YjZK/Y1vRAiBEFe7vWupIMremjYaR3WVH61VcMYMnUCkZKO4O1YSeTg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.70-alpha.8-projcustomview_1572257826478_0.5042345566509117"},"_hasShrinkwrap":false},"0.12.70-alpha.9-customview":{"name":"teambition-sdk","version":"0.12.70-alpha.9-customview","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.70-alpha.9-customview","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-rvVUlERcPJd//oaLzpEvHH8oN1mYeX8P8/+2H9TmqU26tdUjKxXAtPosG6j9sZvqiFF16YvXbEMCA6cUUVo/cw==","shasum":"eb552efe6380e28887d796aa711cdcb954571415","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.70-alpha.9-customview.tgz","fileCount":437,"unpackedSize":933182,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdtsCgCRA9TVsSAnZWagAA7XMP/jJ7jaVLsZOLLczzNpUF\n9wC5Yzt8xpeDHHghpZEXRA4WxiomBtTXQi9gomMegW9eI6R6o2200l9+boC1\njiEPCjkbF9UYY5ovBGHshWFK37bnvv2TpND5NH5wEE2kMuKV89J41ZOX1Ec1\nzgEsSyHNmuLq/zueCMzvqah1aDclLxeRpRq4U01Ws5CzwhaP+LT/GDIn443H\nCRiZ/OSZCKTWcSXcTFy2aPujKwe5ekOV2KePNrmQhOO6TAUJDSzvt0jlkrbU\ng/aDcCUxd6fQIfZaK0wD1Dwnypy2iNhBqjY0RK8Weu06dvDMcGC7/WlrTywi\nDclUN47XnDe81cfeuuopMQmItLA7KKtwYrvcs38maZ8ZF8ZhX+5SZbQcCfS5\n1s6dfryAtyqUwPx3oipsQAJh+E/b0zjC8QSYDi/wVt3HVf4WKBJRv9d84DyT\n6inp3R0CJThRLJ1++yK9BCQFfJae4bpaXna6TgnX/+1oWoKwi2AvyOuMlnPn\nI2u8bDnfAAH7Ly6CX9LOFolewAFEzBAsfBYo+fah9544TnnzviCinDxhE/ZN\ndt1EmdJl6jw6qbYOzDbh+2+M+X+/qsZOy0HhZZzAiumpJvDpWBNAGG8QYOTM\njy49KEhqGRfaVLDgPL4bsyozxKLK7n+3gXrwFbhhrkGIcZ6qotXyHemvfbNd\nmDom\r\n=0Z6P\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICqQpAY+/1Wga5cDWlMl2YVK9uJhDuxY0DLG6ki29AP8AiEA9gRFz7IZFg+uKKOHQQBKGOmxxIiFTMZBB1Di/Nua3ZE="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.70-alpha.9-customview_1572257952489_0.7526934768273359"},"_hasShrinkwrap":false},"0.12.70-alpha.10-projtempl":{"name":"teambition-sdk","version":"0.12.70-alpha.10-projtempl","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.70-alpha.10-projtempl","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-ZgSdTbWBkHq+IEmJnRjtsZDt/3odxKC/5maSIHABaWhUqCDAC3FRrfkhu6HfuvrK1jnn6BriTKVccPpJfDDAQw==","shasum":"98efc3b35139dfe6939d95ad0e6c952b9f98ce80","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.70-alpha.10-projtempl.tgz","fileCount":437,"unpackedSize":931326,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdt88kCRA9TVsSAnZWagAA3x8P/1TL72ZAbl6ZDeQ6vYuC\n2iebQqkBJVoyRhWorz70VuPRiW9ofVyh7em/oaarmBFfy07ErceRa5m6NHSZ\neH066t8bb4pjs4bNRpdUCCXUiVI9GIwa/TIuzeKaiqLj2Hb81VzwVMucBk/y\nPJw5/PSfKSL6Y/Ii/tSfT/tEDKujBEtM2WFambGf4qA0wTjLW1JzNnYWZWBL\nw79yWEt00TzH+ZOCqvjfJjdWNNfVk2DscBuRMgWr9sPQEDjOt67KpHZv8H/0\n9BRDhJFkh5n/4HoVMyAfdYUc/SjS/a3/QNArNJ0mTmregkFcsFJZZwxVTFfn\nbN6j9h4Wa34DAondTRkHFtIfNPBjPvxYlyRQg7ek4J7ij2/sEVHd6E7vU8rs\nirgQqSPGuOQSeVekPinG5od94zGIRM33tRmag5tHl22CvuaaNyJBkAtA4Jcx\nBBA5eve6gmEs7DlEp2JpwY/nT+o3mMtB6dOgfy9kVUR2zqYDvKTQP1GJcERg\nauqtLwPDjltRcZR0gLMniemMg1CE81TfRUCCfTo3RKgZXeTiY+KB8s+uJiBx\nRRD8UCv4lp83cOBPYkge7YRtLjN7zCTtFwFaOMDqassqTHunv63xDX8trOge\nIRifJfXA0OjQW0VBnKz3NL1vBjMH7oKpEDcuS9ibDIJ4NEt+QhRatWmuxupR\nxOIX\r\n=C8PG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIExkdvIBTyjBIVv4kTfRZpv+dxUzG9Y19jsIZ0bzWzcIAiEA52fP1+9mIgYRkC3MLFgGL+Jog0hcfWp2pDPVikRmkFY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.70-alpha.10-projtempl_1572327204252_0.3769033007853073"},"_hasShrinkwrap":false},"0.12.70":{"name":"teambition-sdk","version":"0.12.70","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.70","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-siKvqTm5c0zdrOOrxrms04LMP7f0iJpqHm4rYLVT9RvD22hgNgfQ5Wck1OmF+nyy7zDe9RF6bdvsFbPyzsJpqQ==","shasum":"4a876977230c204c426f03600d67b3b8c3831a04","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.70.tgz","fileCount":437,"unpackedSize":931301,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduD6QCRA9TVsSAnZWagAAG0kQAJUbjVKByDoc1onFLywl\ngV9IIDiY3ySH7I+DaH6SQGXPie67ahPP1rMOFoJicUpvtg/nn5nvf5/toiOS\nSymOWbUohTew2syrRMtP1cmpc0eFLMLSbwNYU8dsjy8qmGKAOB05ZkLd0Xd4\nsO/dXmRGHNlMY+uzVfjPgDS1JwwexJpaHrhDpACfpFTM5GpTks6egR7wcAi5\n50JR4KxzyE4E2RlbIU+3S+rwleNwcSZ6cD0zy6Yro6Lo2tcZd7XBco2V8Syt\n3pB/wRPV+cKCRrOuVMg0ysNpvIJdDc1dYoYv7IDeOLJKNITMaFh2QPDovTph\n0yhgIYK0CHP3QwaG6ZDGsgSzgc2K6AP9uXQPC5YIXkuDILbF54etmHB5RJKt\n1kSV/Jnu9VHoWo4eRSJtRxkuDQ212MxB6o/X07Ddsbe+TJFdjrP1o1fC/BDT\nFa4fZ0xEpJHQOHidzYQMBWEkX/PnHhPW+SqohdJSXYLfDm9jMNiBBbHFcRVw\nuo9rMyZzx7GsVEyQ3LK1zD57Z5O0nQGno7v0atbDMwvgQWYpAGSrh4aidrXa\nSIsn7RumPnLs7YhkPTvu8BhmHCgK03HDzAkthrb5LSQAf1oAk5pky/i4Kaac\nG3PKA8FQ+Whl5hqEJpiiaHP8raJL1kSFsLNJNRJYXSr538gX0iBDq+/Gw2Kv\n5YmS\r\n=MtLA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDs6MXMcL0Cf9OqFsGqSnoUEMKf9/9BmhY1zjoQlOz2UwIhANrF22w3IrntEIWPsaiET9EFbYE+wNG9OhUKleqEz83x"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.70_1572355728004_0.9422698388055382"},"_hasShrinkwrap":false},"0.12.71-alpha.0-cascading":{"name":"teambition-sdk","version":"0.12.71-alpha.0-cascading","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.0-cascading","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-xv0Gi+uq0EkL2gsITYiLaDjD020hYhSHS8hhIq7MKgHhgKZPyd6L9uEsr3Qpt1SXB0LPEOOpsQo6S/6Y1PioxQ==","shasum":"915578e819a438fd76fdbee846650acacd4a89f2","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.0-cascading.tgz","fileCount":440,"unpackedSize":932879,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduPoVCRA9TVsSAnZWagAAgWwP/iRk7/lkZlL527scKjEH\nw6tokrlNiyjfqNiWrAFxDDJS7nxLf14A71wa3JoaM9F+eArCzi1S7Fa3jsDP\nqvMSOEtq3n5Yjj3ZOb2zhCliBdg1aP4RiB3atpGsHLPSv3bHasmAUgIQAg9x\nvhn5dEhUIUtBaOM7AH+z2eaiHdCqmflwqrnWU/7xS5o0Q6M1qX+9taKG5IzM\nG2j0kINc855g9xmd/d6DyhYpMPfZQXkfQCwbJ8ktxzkmA+0fXmfQO5WoBo83\nNr8h4yxMEDvUE+KVt23CYMxuKrbKSIuaKoZOPbPwgqjkjjv9k0Hibf+bXOov\nNxWauqyF1aYOxDOaFfHhPFLFYp64SFdYsvnNp2crctoHPG1lPO0Yno65UD/h\nAAIGb4gGOItDFNUmcMXzKEyF+y7iThlH+8VYo2jUtjXoVCOrxvFNTyvsm+8q\nWk21NrR/36W+UAakFfWYBDKyp+kCl9Tft/cyZyCxnLNJqLPs+PKeG38BsYaj\n6aGxIFrfZK0Lk6nHw+KdJ76jh03W+R4WnG6RYrftjznBBdoNGt6qGAe7R+hh\njv5ma83ag78bjJsz6Yw4tLhSXYLoDwaksm2/XbWA3e7GVCjnlkILLCwjpZsZ\nH4DD4HimT6AfihCTck1Ym1VuK9VaYaHltn/3HiETNrRp0MRo303hpUvX8k/q\n2oPJ\r\n=V5Vz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCYGghlEQTtpf/GrIDZBaFazzkbZ5Y58uyOjigxKFUV/gIhAObGlSH6WhnMFmOtg9oQ5QpgBPetTq+QNaJwo8oothn7"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.0-cascading_1572403733009_0.18096769777569044"},"_hasShrinkwrap":false},"0.12.71-alpha.1-tagids":{"name":"teambition-sdk","version":"0.12.71-alpha.1-tagids","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.1-tagids","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-7t9MU3NjYSNYHu5ptHrnVO/Gaf6AURKBZd1Zyc392KkE2fb6qzcx404l0zS9Qa2a+o3mj9+ksXB7OTrsb99CWA==","shasum":"9b9dc6ee3ae2e7850a8f1196d690ba7a353592e1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.1-tagids.tgz","fileCount":437,"unpackedSize":931535,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduPy3CRA9TVsSAnZWagAA/IoP/ifruJFmbGicvT5y6NLN\nXc0HK29/OxoHXVxt3Y8hzQI7RtTdKp79eK7ncbNWRRnjuUyNbOtrpK2B2mvf\no7Yewb+RYP8OdTXRcN5839/qHWrqTC96aw16/AQSvpUgCqDns6AQwnmVRvtd\nJPOUSjkpIZjNHFoFcLZShQP/2A55bpaKHpnxXlNyG0xjs+Rl2+a/vZ7t4nsg\nYiPfyw97skFf2BiLcVMKFmEFGpqn3i8ZQ4ZLTYhjJL/dKaBf8FFhiDEyPVFw\n9wTq1kRuQyzFqOl9GHGdKG8qcRYFmOVkRRkAjOxCjZUZdGas7QdtZRx/gCBf\nIooP3TotaOFKwDFl1k+vaxC+diweI/so9YQa23+XXZi1j4r441d3MjANMC0G\num9SzDUZIJjEExaIGN7yRnxwt0n80hIDm3o60mAXyIG25uXFQ+TGADgzl42z\ncDN/NyV8AIyopmD0jBKoo3f/cKFUnH6PS7Jo4JoXqhQIiFKUMm9MNfOF3Qwe\nmcsT7w500j04QTKtMmngXM5aZ5zQ5vd3WBWarH81DieCuAvZ7WN1pP/lsnS/\nYZDnhh8Mjfa7wTbedWNjEkueD9HRD6gPqyx2/R/zP1QbXfW12Nk2Th709eYF\nYqJN8KxPKQ36c5/loLsjkM+0qCkv6+9GGvO43ZXuerUDFAAwiJkcAVKX+GRA\n0pSu\r\n=7BRn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDbfCXDu0tKiOHKt7p47HoOjEVbzxZT518MnR5sLX6whwIhAO6n7OqIv6GGYv6nZ/DC2TtuZORaUmra1uoEloi/1y50"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.1-tagids_1572404406834_0.7190868048214862"},"_hasShrinkwrap":false},"0.12.71-alpha.2-customviewoptions":{"name":"teambition-sdk","version":"0.12.71-alpha.2-customviewoptions","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.2-customviewoptions","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-PZCN+jIGjIRyKIczG78l/3DWON+i+4RQaqKXXwUYV/DLmMOIFKn0P2D6CA1iqs9kHGDArp2FXntxOM9ydbJNug==","shasum":"ebecb54d70982a90e397f4f077e3a107755ab397","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.2-customviewoptions.tgz","fileCount":437,"unpackedSize":931504,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduP9iCRA9TVsSAnZWagAAOfYQAJjfoDKtj1uG3Mh9XdS8\nIk4y9YCC1SOw0gi97tylE7amR2QdBPtWDCHLwgJvK3Doa3d8fOwgRh1gdV25\n57LBanvWzR4q7pmZMq1o7TJSxzcRHLmOg32OSvaU4ndhsntmAL7IXt+2eBxA\nUOgo2vk/sCMuYNgQn+9hCrp2jqg+t33F0Euh+J0RLhgjUqKTZs3Nd/0d2Sx1\nlm2nD6JuGbi3PRB1NL4Dhp26Z4ZxdJkLpE+CKG8KEOtYqB1bM97egK+JhVj9\noksH2LJKarzvOmaiMqYGBle5ESDJ+Yob6rrHAkQBVD2+KYfZirqHJUptNXB2\nUdi2z2DPY1fyPFTfcOmaNl/0dzEYtb6CGG64L54DxqVsXCzaEiXqGVxaqL+v\np+O4oH3hVWn2E3U4zRV20EGYTV3hFOnJ1NG8vRmh6xwLO3GpLGIv79YCMbcr\nmQcfrFyVDi+TNw4ONwI91D5IuDIWJ+MGLbSphbipaMYpbfAT4LkuTcCdBitG\n2SAueCvE4FsNR/m8uFi3HO6wEqy2Wlh/c9JuCdU9wm7I0A5BnCEtLXr4PAG1\n69KzahVnFw5L8CxvrpI5VOgsl7l5bBgzIFRIbfll5TzRj49vhzb4j3yEbeDm\nyseY1JjyNd3y8flbcdp2TMXMah/B8BgBPq9vqfMYbj6jzgqY+r2gTH73I3CA\n2wgi\r\n=rfSf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIATcfB/m43tNh+z5YE9VHAvJqsw9+fqnxVRnFoGVAqpTAiEA5719fTWTf+dSPp45Yqu9Y9xatU/ARR89l806I9bBC1E="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.2-customviewoptions_1572405089653_0.9292546698155713"},"_hasShrinkwrap":false},"0.12.71-alpha.3-projcustomview":{"name":"teambition-sdk","version":"0.12.71-alpha.3-projcustomview","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.3-projcustomview","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-mkWBphzvIcabiWzsVmWT3R+/u3rj8CstKTl1DmrFwppv02fYxZp5si5K8KVbncai+4X4OusDcFP/XcHs76KuUw==","shasum":"ea94c0d23711af7fb68ee82e8f12f49ea181628e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.3-projcustomview.tgz","fileCount":437,"unpackedSize":933127,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduQBGCRA9TVsSAnZWagAABdoP+gIBf75qkqXQ6C0SzylO\nL6Nv0rRGQhMfNmroFW/MsBrq2viXfNWkh8MEUCAuvvvcc86YhoRusb5jGkT4\nMjW5y+oXeo7xOexbbrpYsZytFpabJ2JyHjWPU3lU7beEO7iDOglgphs56JpK\n5/H7tO5ThUnz9jKcUfZVDzqWHCbIpyu+3y9HMReJiz+5mXx0BTHOYVe0orIE\nbMgXgl+7dzdFPiYlmUk1tjdzNtY57CzxXFVkLaY9hvyZkmQZ937QfsA8CEcA\nHwObPKgqL46lq8dSXIaIXmFrJUig7ZR6d/JBFF+TfRiwj+uptaSVMzJiEBzF\nU5e9PW2Ti8lGDh2R2XrQhKXZ0YCsSi0n0Yfoq//5H1CMTD19q/ygGimhTQQM\nxu7r0U3S1/kD0vF8jVTXVIfJ4qV+ebrZ1t/G6INvrTPBAqMjumpbn0nMMoW+\nzu21T0lc5ne9+Dv4CJquW0IKGQmZq6mNCcUDlEHjInoFQkKo7pkDHQO4INoj\n0JWOCmd+05DqvqY0FyFLLmb8A5Qw51ey5EyHtjc4VxwDzzq86CJ10zUQQyB7\n13htYa5h3rPZtgUziFQK6Z7VibJVJfhPw8r2yMm69B6xwb4Wq3RCctIae1mH\n+9v7oCDNT4yP0YwEDYR6AfoGS5151JVC7IC0qooe/bUFl5N5J9vjhOBv0BVu\nvndB\r\n=or1b\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEvCH5IPpEi6yqaQjoeBydQIyYwdg7qt+B5W6SxczYV0AiEAvQvccn3wsAl7sAGjKsPnZD2MqjeKkDERFaiRFF2lVY8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.3-projcustomview_1572405318329_0.24273314705630167"},"_hasShrinkwrap":false},"0.12.71-alpha.4-customviewoption":{"name":"teambition-sdk","version":"0.12.71-alpha.4-customviewoption","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.4-customviewoption","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-Liq+zC3qF+5Ifc3Ege222X9NKqjL+zOQrxRP95wkv9Mbbv2T+2TJ88y1eCzudUatr7pUJTqbHz+pTcSBpnwS5w==","shasum":"6e73976481764e109a05744c1b9fa9f5bc7b4534","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.4-customviewoption.tgz","fileCount":437,"unpackedSize":933306,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduUlNCRA9TVsSAnZWagAAKmkP/0Nei7yh9osxIif12qUO\nQvjbjr4e38ux8hzqu1PEd1EzLSRHAFmQ6NiH9iDnan2kID96gEUZ4CuWpSRT\noS0qca/E9JpUkc/cvE33uiAoVFFXaNT9VEddCFziV13EgZ68gbqzZesY8XtF\n2efP4CxERtxJ/pyXHHT9z0oGqYCvpqaVSjlfakjy+cY/T/gBqiuFfaQCYlfP\n5J907KpU1FPkQ6dcsIhiI88Kik8rPE+nLd4rPjEhsggIEhfmVuPIhWG4Yxh2\numrhQqiyZyUyJTCB9JpPlNrUGv0MD7Ci8z6y8yrf5U5IlYLPw1sBjvFxvsj6\nmhDr6xiIf0iR2Jbi4paRac3CceAYNWlz4ybLTtHZ0AYEf43txLu9gLNSRKV0\n7T+j0QDzzvd7e9xnwjKViGMJolqJxWE6GKQJb9b3pePOa6p07lDGOgBqynDS\nvT+QFLw+NcJco9OvMNdSHIW3gDor1UblhILBQMe1HMfJbz9lPv4sX8+9F/CX\nrGFtNWePuDbwHg2S+gNCV25pXbIPnSLG0Jkp8qqa0HUde8/U34rLSgtiOlMs\n45OtHyTPgAh6qklsoI0m3/Bl0sapJmCUxS2cfmUCVehxkrvO8jBBSOvMozSP\nnPZnteVnZ5SvygffPhe68oB+9nnFyga/kJi+EGYt5I8FGyfEPWJELPvulNLo\nvtZM\r\n=g/lB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDwvdmsN1ACpPqNW3WNFIlepZn+9JfRn1s0lySFfhI+jAIhAItpQhxS0ejnE7Jr30+HIx7All48F2q0WC+iV1kGRHlD"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.4-customviewoption_1572424013033_0.3652920897761689"},"_hasShrinkwrap":false},"0.12.71-alpha.5-tagids":{"name":"teambition-sdk","version":"0.12.71-alpha.5-tagids","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.5-tagids","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-CE2OstgLOn78nCLDIQkDlqw+Ghyy0F714XJLUurVUkb+hEfB7c6HMDXiXnmH5e8yZMVz8pIkqdh6uRgK2D9Iig==","shasum":"df39357c7a9865b7c8ccf65983744f9291519e64","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.5-tagids.tgz","fileCount":437,"unpackedSize":933515,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduXXBCRA9TVsSAnZWagAAK9oP/347sxy6QVc2bEsGrNZM\nveE8HtqqLByu5kWPbHRoblpU9Yu1ukJjERBxdyEqi0M9j7rt8SQVdzVTWryE\noUytOmh7OZ2Q7BCl8AQPNIOm1bj4/3a6UyrRze0z8MtSF3v/6kubhGziXstA\nlb2p/knSuJHs2PncJcO0oEXq5SIJ1lE0I28Mzi9R0MRhns4BLgRrvtD567OJ\n0WozaPn6aHlE5TpZnpLxZbWQp03nNdth5xUdBX0FAktOmziXtU5cYMWptO0d\neBdOqec7gDfDuy83RU9hgGF5YxS0LaGsMtKHjymBgzPwhiea6agUhtpU4So+\n1wFWp0XVD2hFH9TvrFfO2n0XkpCC5+M5bzg6T3nwKybWtuzjH7N9JmUYk40p\n3ju+vK4DdTipfl0I2OMZAofTZzujYsu8NjrU4UeiHgFRbGCuYUairDn5+gcb\nlehQRcyHpMneEh32RfJ0y3q4E+YRN9PPdf+WCCWX6qMt474+VqplUwWEEEVh\nyc8r+XubwrFwrB7uRqUtxzetddqbyiIECjOMd1QbdyG1B2XqW9S1OCsi4mYm\nkJs514nPESOnOrLkq/vCc0aZhiybZTrb4OwNAfYbq7PU3ICQ3BkR9qqotgZf\n7Z4SWWOfUgaJw6CB5UboKEnGeg7TIVU5/nkNPOjPLs29zojWmwORtqZwVGx3\nKVhW\r\n=Ot3I\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID/ZXV8Ivg9tOKUChvVEl+j3slTT4qf6GU/edTYOM8ppAiBDpVT3qeljobDZGwrgj28GRNcy6HCGAMxKv4SZm50SIQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.5-tagids_1572435392779_0.6131418613915682"},"_hasShrinkwrap":false},"0.12.71-alpha.6-cascading":{"name":"teambition-sdk","version":"0.12.71-alpha.6-cascading","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.6-cascading","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-CsfAG1EhHYBwaDnCF0s1alXAzTOIWZXT6oZhkSgjJUW6FVIUUrFogQ1j+lKSIYeE3Nrf25nYOczIynRe6lOL4w==","shasum":"9296393f10d3bf271b5330cc7d16b5dd126e4cf0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.6-cascading.tgz","fileCount":440,"unpackedSize":935078,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduX81CRA9TVsSAnZWagAAQQ0P/i7o/iHn5EajhSLhTfWX\nOfIcYdPPgT6DGjDwTRT+QUPoePGbs48QQA3Kp7L+Dx7kF4U9/lIDd7e4DdeI\nCPZ21g4HDoG7RrcRWJysn0zp2iP7c8rUS7Clyp9bUMB7ZN7tVDfSU5yV6J8a\nkhmWpCHaX1kF9cP2p9ZJwK/Xo4Bs3Qqu1Jll9W5AiabPEMT+8/aqDYifTQ3k\nopfzdvXFjKV3IMAcGBR+5qioM15StaiLAhuCoAYb/kdZ++Y/f2S0HS0vud0l\nDVSS4qvRcWNWM7icrPwnHmZJFiyiHSeaJoqXSWgRUvRHo+0LKOlataRXmF+D\n54jtQuIeog7kkPXJb1sey7eGLXfs39ksaPx3Euh6LBT4MgQDBSYDywwVAXLZ\nhLLRgLOA6URixPl+49EnfI6ieLXdR4s2eT2A8ekC3MNJj7RBQMGeMQs2TFik\nZnfGDOvDb6h5dmADwiWNLIrCGKew763T4xB2QBxT7tuoOR4DoPtmoeaU7TV1\nknHqogcEwsZ7ZRF6JAHmHbTGirfq89Kn1L5Ppv+enak2lBdgp0oOxztg70Cs\njhqVCLyG7KEwpZy6abhlnmF76E3F56lQ/l2+nP6Yx4U6rz97pNspQENf2cme\n9dfhtqUq40qh1wxphcLksorSf2pvctojNpzY7iJ7ZD8ykMyDEC2Txazg/VJ7\nc8A9\r\n=zgUd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDSoUd8lgf+HampuCLul7zMvr7c2ndywk02j6hvaeLBfAIhAK21e6MRP9TJFfHpV5MWNQuKjcG+S3pGR0qQu9T4bXj/"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.6-cascading_1572437812943_0.27671381989998456"},"_hasShrinkwrap":false},"0.12.71-alpha.7-batch":{"name":"teambition-sdk","version":"0.12.71-alpha.7-batch","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.7-batch","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-9kfxGH5v2VhTZrWll3xKldCR3xz7ZXJcz3Bhn92MMqPTDfwIh+Dw5P235QtdAZm/FtSkebGZkJNB97Z41vGWUA==","shasum":"aa7752b2d38fc90df0fb93426d46f717b578fd85","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.7-batch.tgz","fileCount":440,"unpackedSize":960189,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduk4FCRA9TVsSAnZWagAA7f0P/32EJIUo13DAsaGuz2ZQ\ncKghg7/4Af97Wwkl7bF/bkzEDpSWi6Ge4BROCUgKIwld0moVRZMX772QYe6R\neE+MyeAtN9RIkKHRcdXd9QskuhTAEw0BborPx2Q3p0KlskWba71RkVPBf7BN\nGt0TFHlRedskJoKe6pAYthQsxh24O9SKV9qM8zmgbVRR5Gqz0bkqA7HjVoPO\nfBli5vE7etbVCLuQ0S2/LZA10z7f76HDaMadg2sOgL1K07W42VeQ/nmdHXZ/\nX+qRpaTzibPA8RUUu/t37XS/PeKg+18zgafaIcjvuCuygfA2ongYb8F+efK9\n69whP6+t57Pvyh2ojYQyvl3iSSrSTL1N02Oen0nlP2xzMS2uq05egjEMfZ6A\nrbXAqIREkRVepUcX4zhGRKE1s5s1HlUauLP42sUghdlORaNLa/yGUyHvObcv\nkQzAvhz0HuN4O9484ZfVzfJ2BdaDGVARCpYV69OjVVIxRJP+xsDsgNLYzUCg\naLuvfkA0tjtaI1MQ/mdcQTHvlCiV3KR6oA7VKfon/eWc+TZ2EbPxTp206qw5\nYEgeR2lI5vv9aObmI5jGufK2khdI8CeWnaCTMAkrYeMwsbix+n7k8KqySwfG\newmTk0+2E3SXnGwpincsktPEJ+0/6cIP1Se+Z7c8evLHNxXnh86nhecHiZde\nhOU0\r\n=qd8o\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC8jd+HUszjzNib+kjXt/l4ctLUJTg3QEzAHb9+ZdeR+gIhAPH0nVQOt+vX69jo03iLTWtejsoowDQzYOVK0fcMbIZz"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.7-batch_1572490756542_0.09164704614553743"},"_hasShrinkwrap":false},"0.12.71-alpha.8-customviewoption":{"name":"teambition-sdk","version":"0.12.71-alpha.8-customviewoption","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.8-customviewoption","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-/afolcseLm41jho1y6w9Z4qA2qB3iBQNgDn96krwlSxCXYulKTNQVB6vdHpSks9wTpl2HeJTb7BW57XvAhMlbQ==","shasum":"e6f4e2fe5bfad34dc503f6a90ccf09020dc3b241","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.8-customviewoption.tgz","fileCount":437,"unpackedSize":934107,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduqyDCRA9TVsSAnZWagAAQW8QAKIez8v1TUildgI9H8+J\nYbRih2/OJKVOojjJr262RnH6xFsCNuG8KuhoclgQaOuhbqtvRlEnZrig9ve+\nXEuSNbCO4Xvh5ZmThtVh6s28NpsdOyWubzz6wSX5kfJtLy0AFiG3JZHSFWPL\nZwBtVs8DHtoZwjZ86KyXuzZFkTTdie73RzLzv2muPwLOLDp2pclBhfUycquA\nmxBsq6shXbKreM0jhaLX8mm8oQQkCwWw50868rQUYodxa+MyocLneZ3a5qTZ\nqqlVAC3e4ajS2D/Vm2jCTXSd0x8yoOVdFIlsRIH2hNcb0zMkE7YygWutpjLC\nQ0XszQ9vlIB23sfQi/6N4jYXUmuB9fbw2Z0pUsgpWgJgIwZZwuFda1ND9Kjl\nAdn9+8NJaraFa0QmAeXivFXilT0opszoXQHipKK03soPOQFtqmWnpqLfQ9qa\nlwUwL1gZ1tgikohOt4zGkrkO1ZWEVEYYf+aeGAGVW4tlFlbTZhZyYgrd6DgS\nINt/kh8dKg5ZIM99Outlde246p4A5oXxwYM7K/T7SBQQgVlpZo0XfnZfvMKa\nXtKRGly3ou6EelriNQ9BC3xEPEi3ZX6Hy1xoCh8ojxpfr+FkDI6ZbeeZIvCP\nTWpkLxiz//2j3SSvxrDUtAkewzEXFL1KXWQ9L4v6DFuEFziAOvw/UY1kf7bV\nwaTc\r\n=8GvY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC1rvvgD0eTNKXN9GOqHkeZhXDV0TpnGnMOj15rgleEPgIgbbzYVnGimG/FV7/5vMcDCh8tQEEUdeDR20akxUWGwrU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.8-customviewoption_1572514947213_0.23542159858837297"},"_hasShrinkwrap":false},"0.12.71-alpha.9-projtempl":{"name":"teambition-sdk","version":"0.12.71-alpha.9-projtempl","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.9-projtempl","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-yGiE6Rn5KSv2IaZAH8rcBzQuo2UPFlwDs/6oFH03JWl4gRyqtKEyceLxGqxnMxkPKE84JZEy1ZuS9bVAnHBTzw==","shasum":"f7640c5d7f23adae7fb41bd5f0d8d4650a4d3df4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.9-projtempl.tgz","fileCount":437,"unpackedSize":933580,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdu6M6CRA9TVsSAnZWagAA4ikP/1+T9tCop7VU35MrMOFO\nEUygM3hvr6YhxRpTrsFLnnQTmUr62rIk5ZLLaSIjzwUn98S6uuW2gBlRwwXv\n2I5ceqodolKCXe01uyJIuDgPTUSqhcxf/g1LL7qeZ1FsTguWmHjkoMkoE0Gd\nq+Kx8dBIWz3qDdoK61FD3B/B3czfb0J/gZNiR+zI+x4hCf1+4sM3JAQupgxN\nSd8Pz0JgN/MUBXwP+duBYEkYycrWeE7Ho01ngy+X1jgwvwDseCua9waTqlin\nlKeEHccRgfawdze0lNnXqQ1d07p0dv2MCfqlPB4XRdJ0z4AWKj56fYmI9iQS\nLk4AlWsVENZUHYn9D8DUWvty72tED2tOo/3qeSCFnIliBYjsahV1OVK9imak\nJElKyCTPkuPWI4KnBWJURPYPAAXMFCl5up5cdOtAchMR+YQosG1oZCNFPlFu\nXQddck/AHYZ3zVDhqhtgKYtkFzrGHMXHvZQjZ3wlJ7YzJbC9RVM6Je4WY0Qx\n+IMnj/E2jW9j+OtaZcL1iTN+Z9CGU6+c4bVsFNA2C/oLzsVbT9GZ+dSqg345\nb39VbQ0QwTjiWdR3Y/+GwSIOMKJc6DKBYH2jOi6V+MfLpn/q+X/xlajW5ySL\nBuXlRbUj/fQRA6Emmq7G/kFE5hiNOvNSqG1zQsERSQlldCL6OF6pqCdqGAj6\nxBs/\r\n=R5Ob\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAVXiClP1SfEe8T1lgnvAQpJvoq3NHS4QoacrfA9//75AiEA2XCK22mjIK8biNFedNXqw3e1W9Ox40gnGZTsWH4TXHs="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.9-projtempl_1572578105552_0.7711040305276373"},"_hasShrinkwrap":false},"0.12.71-alpha.10-tapestry":{"name":"teambition-sdk","version":"0.12.71-alpha.10-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.10-tapestry","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-0bW+xWky4eqjVdVE8vGd1bBaY3vX7uDElqLLNIUkuNVMtOATeL7C5ZJnsyccL1kVu/0g6ed/ZU1bi5SSlJKnPQ==","shasum":"0e830e5dca97d905f7a97ad5fa82e62bb2ecb0cf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.10-tapestry.tgz","fileCount":437,"unpackedSize":934655,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdv9TVCRA9TVsSAnZWagAANq8P/RxgSmkfP9x7xEa7hpF3\nmGr3p2FJuGeRTw1HKFOKHaYsPRzrn0WtfOpQcetCug9MF3AxxmJaDiq8u3Vw\n0esTcKUnLXBxOkM7Mizgv1wlpG5PQ8gB4bs9CuNDFBf5s2UbLqXrj2cqZnwn\nPkHac0P2vftpVDKUV70s4+CPbSOZlhnYZ3NfNylCfzJPoMI22ftyYSC/47x/\nD46FmDHZeQx1Dnwx3D1oj5MHm1kxLinmCf57ZF9I3jCLxBUBuLeNVeLXfbx9\nFlraASNP/aKGt9n3Wk0IJcWvrUZm4eoqw15CHW5Q/OEBxeDKfXi+DBhHQV0V\nIVdU95mhOHJF0ezEpTBEAwr4Cx6MRyEXbZhb+YlkhWA51CABSWC4PFSM+8i4\nrwgzc1sq9V996Ddvj8n45jN44/zElwJFtj9l61YxL7lQWZV+cQ5AP8D04wjC\nvdwfg+f+nL340AzLPkS1H5uHw6nwT06YH9CuB/4zEOA8Btien+nA3FgaYBSp\nesXikclxn28MmYUs+yxjbOTGYXhAehrC1L2jcQzPmX3/RkjUhossBp1LCDVX\nU9QN21+sOr5HlcLCJWckhSdiOUK1mkYI/Mq7CHoR2OWKMujDMR4UQ+7Smqfi\ngRD4oVyqocR4DqLQ+EObl9TE0lKByky6+JY/vXQNEcAC2sS60lYFaGqsXwy5\nu9Fo\r\n=S42L\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHbkM7jXKIqP6uMP1quVOOhHBDByqSP3pGS0Kr6+lM/JAiAtc/EbID0SlnguJaBRSqLVcFpDmBjy4m2zpsPWXksf6w=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.10-tapestry_1572852949275_0.49406338339552125"},"_hasShrinkwrap":false},"0.12.71-alpha.10-setmethods":{"name":"teambition-sdk","version":"0.12.71-alpha.10-setmethods","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.10-setmethods","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-G1zfacMO5Opd3WmSHoiLBQLxjX0ATkifU8bFdTf7PVTBKpQS+cEMOCTuTquUTggRZmgLkGb/jEMBwbuE2lejUg==","shasum":"5e34176625393aebee18829bc84c6977b95ac5dd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.10-setmethods.tgz","fileCount":437,"unpackedSize":934629,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdwNV7CRA9TVsSAnZWagAA1UsP/jxRt628D+HAEqtgxJYB\nx795WMn11HYWvklBVBuMQWJE7GP/jw/y3HLk2IvwMNL8deowyHS6zxVpwR9M\nIWEQOvxbkqMkZ2qV1nDyRKgFlnIvH9NAPhCjT+Yrl1/4gFJxFmKSjxeBPlL8\nvxnqEL9mqZc5bl3qeI+z6W2Zk2E656lt934esu3skmQStkymFr9sUB2plG8m\n0/5Fw3SxPtYBSwhv9GXVGLDVFsgboTOV9Z45YfnV52Gvl5b7kLsbaqNkiaTG\np7yUWUCz5LO5GJ6AxIh5+n17tO0ZRd/1LIKZOez5RypsEazKFHO/XQMLU8VK\nvtaSFt7y1UXUSyP7FGj4obBAj9W0uDAPJytE81APfVQeIny4vH/lKR5rpJgA\n4CphST4y3g0/xhaIEKl9wPMyPfdMF7j/LisqhCQcDUWefJ3A6KqKRk9t9Fs7\ndMlGntM5odGYWql96K0uHi1Jlerf+ke0t6X8zAXYGWQSY0sMNKv+oKT+U2Ex\nDp7oc4/PjaEa+sovVgr53CLDkN+s6qikRxe0oXW7DRs7qtBu5TvFp9JLOvmL\na27cv/TqhXhplC/tIztAyMy6y9ZRRQLUxD1BtErKmtI2JoEsKwlHw7j65FnZ\nneNMv052eeVk1OOAKyrqcN5e2U9YFirMgA9jPgXyoV1GTLcLqLM+mXQNlDJl\ndBwY\r\n=Suvb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDYYL71Fu5mPN9JXCcr62zm9TkhyMMrb97giKkabpX0ygIgOlSooQqUL2PwL+qIfySbQFymX0c2HGr3PFsxiqNkUkU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.10-setmethods_1572918651128_0.30446276425442464"},"_hasShrinkwrap":false},"0.12.71-alpha.10-tableseethroughsubtasks":{"name":"teambition-sdk","version":"0.12.71-alpha.10-tableseethroughsubtasks","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.10-tableseethroughsubtasks","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-yZnH0JhZZnFARVtgEXoeFJrkPXDKEozMGbKjbnQx1dO5tdyniT6MCw4W9PeH6xLpHuIlfh08BQLRO9XThcQbrA==","shasum":"e30dcc315da27c6cfef3418c83bd5e6397aac0f0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.10-tableseethroughsubtasks.tgz","fileCount":437,"unpackedSize":931416,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdwODDCRA9TVsSAnZWagAA8yAP/3ORZu2uNWwzIsgYx4eW\nIAK5vpLLyBlQXVTUaf+RSJCUuhqoCf3yREw2axxQ1kfKBvayh/ipF+S8fzzn\nQrKbXmN3bhPdN5uXKYonMOtKfMCJgc1zWJD/zA2ExCA2jsn/3FWt1lrN5DJq\nyuQB7mFwYc1B8vr3w2C1EL630oMfoWl9QguTzw6wwe9Zn1nMMSKuyFeyEcg+\n7sZ9q9BXpN6l4OeyVlm/2d8lwRxCr7LNqqT0OjLlXRSu2pvNOdEIAx9RoxX3\ncUGaxpfXz069z2RqA0wwiCGN5D7Yv2on4xL/jmViWUbpANKepMpHAysr7oBZ\nM78p4VNvjrcj49YAc+RBSF5l8jbxzpJRnYhMuUTBgAwvMZzxW0Uluibh/kau\ntdYIWWshRgCTp6wEskmvjB3YGVuIIiUfATRXX8Ofl5RklByxSTKVKEXq+kJB\nQTW4rPAXgi00QC5K9wmvSq0eeQWA6OTnAdYQdOSYcSkFrZg3c4c0UFxLPypI\njwMt+SBmynUrYc8b9Ng7RFybtlw51I8Ui1R3H/SXRARCqB9ptwbJbvyhaLZd\nFuewlNnZiNNCGwBGBrUuzpQRiDkRLc3yfTYjjmhnxUru9szfQd2Iz87/YyN/\nhrKMCzUDSmb03rOZqmXj0FKahUvaCRoGozrgFC/t9t5i9xLp5orxdey/B06F\nfv8X\r\n=m2pM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDeUM2Oi94UK2+ktb/JBAWsnZrq3JJnv+IFfGGpN9tbvAIgegL1de9LKZ3lyrA6tHV5i0q/0he0FLU7WOEsDGU+GXk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.10-tableseethroughsubtasks_1572921538322_0.2507432627161297"},"_hasShrinkwrap":false},"0.12.71-alpha.11-tableseethroughsubtasks":{"name":"teambition-sdk","version":"0.12.71-alpha.11-tableseethroughsubtasks","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.11-tableseethroughsubtasks","_nodeVersion":"10.16.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-4mfSnOygWUGqgxOk2qq05W1zQi4SkHktoAMRvrW+cWoJ+5pLhSMDXwb8ZlkpK2vfAuj9wwFhE1CZg7wYSfg9rQ==","shasum":"411c0b513881af7775ce83d39dfb35f2061921b8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.11-tableseethroughsubtasks.tgz","fileCount":437,"unpackedSize":933615,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdwOwaCRA9TVsSAnZWagAAtIMP/AnPiTQ9e0+UWl3NPhjL\nskOw/Eo05DYNeD6A2+5bvW4GQDr2x6RBZy9XDYDQGpnTGyPvEqhdOJk9jGmV\nt4s4uDz4jUNAzwfJuWly5i9DxIE3DvKzCkA7kHMhw5TQfoUfY0aMuPkXVOIe\nhPNjzuTs4x39EmBTld/sIcMsFRL9Hm7PcSy9kYfe5Yu7XrjZumuV/tIkD4Lx\nTPBsQdzOqqFYLgPAbbErLjMyzbcuLJc52wHDJU2qTTY8a7BjfvV1N40j+/Z0\nLMKeW2vN9AdBlwiiwY7XAiDdjflcTvRZdjv557UVpay1tua60sHmRJu62Ts8\nZ6kGYwx7LZROXWUbCTueTV2977d1Ctj8Yt3EGjihdluGl1x4hrniME8O+lTH\neaej5hdgQSXP0/oSkQR9tUIn40qnzOgXCq/9HnWwzRTlF5kU2yJ9ot7Wx3Q8\noM7em3/SGNXLy8VWj77EwCT9KdIQSfdHjxZOYfjdhxamEhQjxhL4tgkx394r\nN41GdQwXs+73sD0+4mF66DZQhweMBEu/4NVWXZQnS5oIQ3EtvdXt9+igBzwc\n8vTgDsTR+e1yPg6/TUVWXIPv9yN+7YflPwqzk/ZTqbobZ+4tqelB1v9R/UL2\nePoV4r9OwNoagtfrCgVq8KRCoIYh3bPekdCOXhvgQVLW4L6/TpQm19wnc3Vq\n01lS\r\n=LKR6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA6eCPoMQTgMJd8t3nKl5uaYJhEXJKOSYBUNqfstQTTNAiA1+yr8YPTNnYJK0FDlc7z0C4CmCdO7afySEEsDD7dDjA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.11-tableseethroughsubtasks_1572924441628_0.9210367337968"},"_hasShrinkwrap":false},"0.12.71-alpha.10-fetchclient":{"name":"teambition-sdk","version":"0.12.71-alpha.10-fetchclient","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.10-fetchclient","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"dist":{"integrity":"sha512-v6napxw5/q0t2LK1xwMiT5Gazi9wLcpxXlSFHYG+tA6qFCcYt638Wxaldib3EpmDE9KJm6oCYbzXpu7ZLrSp5A==","shasum":"219c6f476578625a32f33ff078089017dfceb46f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.10-fetchclient.tgz","fileCount":440,"unpackedSize":937964,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdwTd8CRA9TVsSAnZWagAAvEQP/RBXTV4dt7+/U7RfzPwg\n+btFYGanaw1R+W+xdpMvt4rNW5j1bZUkpY8cN+o5DJ7c3GLCGXbVg++6Vsgg\nFdVj2vkIa8TpacS+JNgMDRJ8vFCUqiN2UARqL3lx/uxqzbInI3GTBHlenwJY\nQ9SNe7l2fYT63IOYbzUgd7vdtWOJEOLm3iFJAB1Vw9Lv7S5ITHUK0FDmzIYf\nRP4SOUEHbXxXl5YMKhx++o42w5kq0OISVPjjy228kz8a1aowwZrRmhLDby73\nR9WKkUIGKWBGWMk4bSKdt26Ag1i8RM0RNTYpakQMqfE+dJdpV/Tl4ftkz3Sx\n2EinTFastr46OQqKwbXZMryitRGiHaJaGuK2CJzEnfXy3yBFrd4uvK2hRMkF\nDh4/ehU9TXUxuDHisb2TusMOmzh0kiTIolK6F74S3Weo2g4OREmjvr0IhtyZ\nVziPU74eV26zF/s3GLnInxJN6Gtkgl0nYLHE3pS0jwWxt7nYnhTNiJrMbaN8\nn7ZTJQW4UZIvmEfXzmEf6I7UTvFMNEbBsvX+4ON1oRLP3e4TneH5VzQTOAc4\nAIbpE4iy8Rksi58hP6yYHb6EJN9CW0sJvJoLKuZS8OYlNj4FLb5XBz9DtYjt\nKRKWD0r742eyIL66lS1h9R4w8cJNdHjYdu0FIW3DWJzk8jw6dkGyKQBU9CoI\nWZJ7\r\n=Fnlc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDLcMMK/2UoLtFxw0J9YhrkTRDaxjnq3gCqkRKeIYlVGgIhAI5jsOADRi2kRKnfJkhY9bmVnhjFV7Xu5UUppkXmBuOu"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.10-fetchclient_1572943739475_0.13486388438950736"},"_hasShrinkwrap":false},"0.12.71-alpha.10-fetchclient.1":{"name":"teambition-sdk","version":"0.12.71-alpha.10-fetchclient.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.10-fetchclient.1","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"dist":{"integrity":"sha512-CRWqM0XHvbT1seIgZ926DfW+6BMP5iaY65iXPT2MPsJzV4efz4f84eT3ZHySht0V+Ufnx051Bw/f6/6wZc9now==","shasum":"f4d957c5f05aebf57bce0f4a7eb50c03b133d82b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.10-fetchclient.1.tgz","fileCount":440,"unpackedSize":937966,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdwTj6CRA9TVsSAnZWagAAAicQAIcZsrCzbi7t/hBuwtks\nRZ69Pdn4NFdNd2mIiDAgkaTPWKbvSrDyA2CQhrib/8B5VisIq4MY+OOxrNn7\nEKhJ/B/HUL5L9Zd8+i8HybjhiC0mEhFfmt0K3J2B+MAOFneaNBdVpIEQUnb0\nQFgETvU9A9TbO49dWn2TyDGwY/1XsTAXixRf71Xt/WsgID6+dHhVGb3nNR4O\ntjA0AcDEppV0TP3Y/5NEWASNmXATI4JYZpSkgtKtsihSkUHvupl+5EtXbmhW\ndFl6GlLx20d1sF0GcxuGFZw6IJAGXpXiiw3Wejz+NMCndAeiBIwGkVS9yLf5\nQS2cAebUJ69SybVfVIGLDSggCGsCrI45jDmH9mqX1pnSKqw0wfj0e4Zb6fXj\nbKEM8fPQKE0v4vvUH9zFK45G31BX22JT0w3+AYJrjg+7aNmCYb3jdMhLIdsQ\noyzpPQQqCIpQem89rGszOmeDl0uvRC29qQFq2eAwZqWT2D6e/up9l/d8+nyI\na3qKJJ5M95zC0uBiJFFHlyV/G1dZJ1EW9aDXefkFdfpB8RRevJDdG21n8CJ8\nQwSlWZJ3VqMDX/mAUxD90S064wGYcwWi/wSIW+m4rongz07obZ7PpMiFstTC\nT6lki9USApMIMtOt5hvSScyzjh8UzZtivVm/CYDQZHlXeY8FigwA6QPUgMmF\ngr6F\r\n=w/td\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGud81zPZs1BAIUUdN9/sJS4/HMUX0YZj0s5S1tIsF5IAiB5AhW6BEMKiMr61VdKApaf9919vXzGEVdUz5p0sph05A=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.10-fetchclient.1_1572944121986_0.5484782773886869"},"_hasShrinkwrap":false},"0.12.71":{"name":"teambition-sdk","version":"0.12.71","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.71","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-DQ13U9FxLIPJCrK98btN/oJVBymQWZchGtUq7nrsGRrgh7EHU0zH8CY5HWr3Lit8n5gwKuTNuXKTOq7857TRtA==","shasum":"191188021b07a7927d60d55505bc740ab7d18eeb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71.tgz","fileCount":437,"unpackedSize":933729,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdxUYLCRA9TVsSAnZWagAAq24P/2EnABGKb+zrXUqT1rUg\nbmwZLS1EKZh+4+P5YCmE0yn4ukGfj5aL/hAXymX59ooJiUckb0DbsXZDCl1d\nmC4sSh/NpftXog1yvlQmCwQpyMcj1D8le/22iLkpp/03r7au0Pupn4XRnkky\ng845PkcIHZuukXjlpSAB5zUdPrhG2z51IjTPHHS/tT/dM0S3KAUwIl6txfs3\nHq8Qp40zZA7rLPrAxD/uxXo+yWwFT2jTrGFvTVRislj5eDUhdaGR/kA8CPah\ngUzC+/dcBZY4ICsFTOhHvnAJrTTR7jbrpmI8tmscOaloKHJdUpqhbvrFOUWP\n5Cai0EgSh1aRjh0+CHL4D9gHognIDC7TXTz19qxnw7f7w6Kqgw4jHVW+p5gI\nnCqOYl+vM4lvCZViRMURMLriyABCflDkXiNfOi6HOx++ci2QBFNIOybPLzGq\nzD9HhNdP+wbfU1ttuEVYnE5WotwVWzJrRveBYVwnQ1G4BgpfKdmrmGfQfr71\nC1c614n+e0lL9OLxEUwx+mdr2Py46/tfvpGGkVxpa24g4vjBOflEA8YIvnNO\nKcV/fW+Iz4Zv5WXDd8Q2Zx/BefKD4fzjkBVTyA8nIdWiOFiQ1p8GXy7JdG3R\n98NBfM1Vu8KCvAkj85jqeTsytF/890XShWx7UHUaHHHiS/1ojM4ErCqf9p/y\nlI3U\r\n=g1Or\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICBonPniV7ub1RcXkqsLACIdaUqJTqKVQkM+Ap5ohoTcAiAYWNQAvP+ljGuyqq+z6ocVNYGjxBQ7aKiEBQTIqtOjDQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71_1573209610969_0.011276560663496804"},"_hasShrinkwrap":false},"0.12.72-alpha.0-tapestry":{"name":"teambition-sdk","version":"0.12.72-alpha.0-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.72-alpha.0-tapestry","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-9ir+TQdAuj3vX2JHmfyBUoduH1s5+L2QSwmP+phoXlvYxd2ORHxHxEVnVllGWrK/8jAf0nwu0/8E0JG99uEUJQ==","shasum":"de20e76c835172e3515fb6f4f43da47aaac8445c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.72-alpha.0-tapestry.tgz","fileCount":437,"unpackedSize":934913,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdxUbGCRA9TVsSAnZWagAAZnEP/2cGs8RuY7qzR+UKPGuL\nkCimRefKCzE1N3PA3qoCmbVfCBfl7WOpztHOfma7OjC0IwR8jahU9BUrm7Tx\n0WtW6PLiRGBv75lGUGWe1jmRkoEl+WoI9y6FsRVmVJLlVgPlsuhZ7OLvI9+4\nH54HLXJNNrl1X8vD6YoIQoqKjfcWompzVGJbcQJG0FdOwiquLny1Gq0v1wVg\nwL7Z995vgFHoiVn+wHaIJFuUhNtMQ0fEVSqD/2iSYOlNyQ6yEmujKAFuuuGp\ndR0zsKc/3W74BblMgqf948TARCLQXuiDy++8U2DuTI3aatuojEmi4u80SaZ+\nf/sL/HCgKp60k5xwmx5AK4lNPuxp4ENV44o8ux4q3jvbcg9FvX8GpUBje3ya\nf3k4ZR4oljqd3USwVKfOcaOtO77rawU4kfvVrHgJTGVubCWZTfCQYvouXHon\ng5wmAFRqhEpdYiHPGQF4D2PfhICYjvgE97R89KioGRzIP08aa5e61PUUe0/6\nrbJnTRqC96p/ein2pE5mfa6X2QE+R1laaEA+W4zvGIKylE75U8ftG+0nzgbL\nc1Tjegy5c97Z8VjiYcKlcYj3cMzsN51BQXDNeHuh/2A54IsdmppKTI/THW7n\nUKVRQ5s8UKWRobBVNqmUcwEbh5INVBqY3NzVLeGLTsT8jOjoU10Sv7gMWxWk\n2cae\r\n=gbNs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID1pjHNOjRvDP94EqvBRyeHtAs9mMBqfHwtc2NJ1bst7AiEA0irhqgkGfY70i4yjMy16PkOt8Za1fjJk4DNDiovuHFo="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.72-alpha.0-tapestry_1573209798086_0.72049733317413"},"_hasShrinkwrap":false},"10.12.72-alpha.1-sfpresets":{"name":"teambition-sdk","version":"10.12.72-alpha.1-sfpresets","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@10.12.72-alpha.1-sfpresets","_nodeVersion":"10.16.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-y08oKTbWUZjTyhcTHgVAwdB+alcZnRFtuKzYarVLkg3wFwzBqfTRBxeumDLs9oZcGjdMb+gO4nlRvvsHt3AY5g==","shasum":"68ddfdda02c1bdff4f803949c0d69b50de5f8a94","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-10.12.72-alpha.1-sfpresets.tgz","fileCount":437,"unpackedSize":933862,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdyNHNCRA9TVsSAnZWagAA8wsP/1yxCr/L1S6piMRIJc8C\n0Jz32uGF7FqOhfEP4zusZh4UkGwNV65gXy3RK9x2JJN8viBvgwpRCGieQGj6\ny/3KwEX6HlFCUMNwAOV05gGQctBx7J7v+UanfKpPptvVo9yRW/YEZv0Bw73h\nSS3FEW/sP3r15iGcocsWyknu/WQmnGI45QLRqPFrKBUJ82JsL0nnMSKnSWgE\nBFVVwotpllSNhpmMc6TWjWywr2SNoVafMFhEz0kw16TiZnjF0UvFaIJnqKuq\n0WNmvkPiK56LzxKhbYjaITwVGgaDMaGXuwf8bIB6DD+nxjcagWFqcX/TX8oe\n1s1ZC13JWMgaucsQzjYt3IHQFz7aArMTgzHgJlRyKU/RzSDJk7I0MKz/tIrp\n4erIOSap8uj8NZHS+KXFg5hTXIvojKcsDsA12kSTgwxzVUjHIGGhOHLN61fO\nM6KZ7xb6LwRBN294dtw6hHr9AEqgFBzDLxW+SjkunIz4orvsVfzs3VTsvHvj\nkgUGS0WGDRowLV7omVTd36VpYcCBB077bWi7W5GH/6u9jck59XQei9fHjz8R\n+i8dsiwQovYp/NFpn88lvlgmNp5nwbdTjgwoQWwzWLo1zmrYjCddFmMfn13c\nkY40BoKelV3V9XWn+ki/uaL3HpHxKW4+VgQ1dURyCP90J8aH9/Ky5OGh0W8g\nHGve\r\n=eR8t\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID+R7YZv6c9iupkiOPMmG33rdQ5Yz+0w1nZ2MjKA86DoAiAex7FKv29GBUqYeAwHQjXr1EV8BAeFRPodcLNJ1f7Rww=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"tb-web","email":"web@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_10.12.72-alpha.1-sfpresets_1573441997372_0.35248916306570566"},"_hasShrinkwrap":false},"0.12.71-alpha.10-fetchclient.3":{"name":"teambition-sdk","version":"0.12.71-alpha.10-fetchclient.3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.10-fetchclient.3","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"dist":{"integrity":"sha512-keD2ovSeni/epvEqYJY/fcf22df6GncVyGnrTJ8f+/eXuatsDGF5BS0MTygEbHShxdjnag8o76jxXBJmYDatVA==","shasum":"157cf457e034deceda23efbc681c220f31f83bfd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.10-fetchclient.3.tgz","fileCount":443,"unpackedSize":941184,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdyhJ4CRA9TVsSAnZWagAAVYcP/08qhrY/B8omKtV5RqQA\nxhe2P1C1xkFCzrRY6q1o43W5lz8t9Krx4KoHe4TgQdoP3cfnqPh3seQgZ1sk\nk5gThLS41Xagk7V310AJfOIt6ceJ6dQ8UpmNQZLbSBxe4Aw8oB1o4AKYjMlU\nErdJZzhKY32ioD9AkWNwQ/Y33R7djsMsoiuj5iOgVbFYcLrdzHwO4GfpBqT1\nllw6cctTPoRpUZZRGJCcJbCLQ3vJdgpd+nnwxXp/FelGARm1Y1muwL1yDtXh\n4IYT5n5Ebd+dh51szmgv7wpQg9UKrFoEfjCydsmwbmWZuhHOEi6kbZ98TO7W\n/TeFsWnHL005Ri5Vacdenq3hN0XI1AZXFBMbOPTY7WKiDH3V7LogoWlowhCS\njtOtEC6q2DtgP4S0xcar15uRgkPC2pdr9oTpqXA/JXUWybpC+mk/8N7xUkFW\nhugfvbXibwp1at3q9LrkLLHj4h3qBW4+kWGuZ3vIO1AWubVA8ZQzgLXswuPi\nZRuNUq+ovy4QJy5kNojAkjYEcYdnEfd8aGC+6FvuFRyG0OCZnq47wu0bOVrJ\neg4tkxmUVadjhOn+y9coT/es3A/zZBfWKPsrV9qKl76mSaH16dLXDzLz0YZt\nDEoBPpihfjICCFQhdPgv/uflsPzCYcxQvx99E5bGDteXAXl4VaDml0uHSWJB\nZCjv\r\n=wf5W\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFIAsuoNJS5PLAFfguqA5dLWTfIcA4bRYRDUTmG6sFUyAiBYv84Ii2sd6WN4TaJ9EKSq0gY9AHLNu9Wo7yaIk2PiBA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.10-fetchclient.3_1573524087449_0.6982488401762166"},"_hasShrinkwrap":false},"0.12.71-alpha.10-fetchclient.5":{"name":"teambition-sdk","version":"0.12.71-alpha.10-fetchclient.5","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.71-alpha.10-fetchclient.5","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"dist":{"integrity":"sha512-UcOIgWflCE+E5O0kigceHuqvJ1A7ZffJp2gsp1tcLWnVX7bVVsBNXf3C/GF0Oav+DEGYXN5iC8yA+ibinoZdAA==","shasum":"beef35e509cb6cfcab8e3ab5502df86d33a907fe","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.71-alpha.10-fetchclient.5.tgz","fileCount":443,"unpackedSize":941277,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdyhqOCRA9TVsSAnZWagAAIfQP/2mc3DZYnphonKGy+hmw\npc8PJOjOS9ppxqRo/2kEMXSnq2/JdfQ58DMyz0UjU/pdef3bCEM1pqMpI6PY\nIakUH4ZURN+sNCnR/DyEZa/Nib0QKmJg7mbXSGJSf+rSVUgxzyGb0+NRIHbc\nfzMuRhWZUaaRdeZaD1J48rVUhlOzwW3+xNFU5EMUpKtEkPhMiDzdpRbdvqYU\n1wqqohhcUYgw/4jcXjZHC4DBxyBQx6Ib+/zV91SJsdGHMDEDM8W09OGaKMo8\nrvh7q6axNrZiJNPCfNcxCBAcC5ChFNjo2nlCUheLoL1W3C+nkkNs4RaYuIah\nsQvDehOUONslzEQ/dMQL+IEPoebW6YIY1cWIx0GSPEG+/aTwE62W6MEq1ump\nXDpaMDDP82ewEzWumbk7gER6PSpoDID4gKGR5FTz0Mz6ZgUIV18+g46VSTo3\nTubZKcxpBT8mTzG3T+D8RUQENPNweAO1fIQHSE8MYO3g/DW6hpE1++TnA4Rm\nvu3O8PrgOD1IyUFVK5o0L6fz6EA8n5wxRy8uPUOZsV1f1iS8atHAvUTkd1tL\nXsFv89HgxKHjAbpXFgqL0405ttcyM90d0NP14LFFu6XBx8T7ccwD9cc8ySrG\n0hQwnW7315x4svfzPNtkn2UOvoJkaYsTiRKysnX4Ex0slbIjpGBjbp5Y+jZb\nrNa+\r\n=0/Dh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCtr3w8X56L2kJxqNSlfib8wSytw98yl31cTYkzAPnsaQIgX+tHI7bUpaB2xSdlGwualIADkBZPxA0UFu43O7400M8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.71-alpha.10-fetchclient.5_1573526158094_0.48901586523731533"},"_hasShrinkwrap":false},"0.12.72-alpha.2-sfpresets":{"name":"teambition-sdk","version":"0.12.72-alpha.2-sfpresets","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.72-alpha.2-sfpresets","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-avMBvIhQ7/E3nBY4SENP7sl5zyrKmWuTKJnNrlMn8hf1a43LzocMifHZmqyL/NlO62hzsXo7ZJ0Q7THWkXUxzg==","shasum":"25a574b43f5eaf05191e25b992ad4f846aedc9c6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.72-alpha.2-sfpresets.tgz","fileCount":440,"unpackedSize":935421,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdy7wqCRA9TVsSAnZWagAAmtoP/0xVImg44Tt5Nw73HrR0\nMiolSXzHhOqpDYGGXUkr6FMDgTVxRMOFVGo9buGDpbvQl9J/dUL7nGaJ2zns\nb375lUjwdUUs1DoBTJS9dkxGjRI/czP3Nxm2a+i+gfOXPIa1ckHDUglVPfEZ\n3n+qPN6wcp7WH3ppp64J8Sc8s3HC6vP2mp3JCPss926X1t2V1sGmthd0yua/\nT7FiUT/hmV9CeCXKipdRvftI3fiHKBTxkTMuDaa/Qux3IyJ2nw9hEBwfpvsv\n3DrFXGPo+4YcpAOx5ATFgwttc/ViphalMWcXh/xfn2IQcWfAvzAJ3c25LGz4\n3t09KruJfrfOtnP+EzPWMADt5qHw6a6J8RXu+KtjvbEN8yTO0qY3OG19oo3g\nzSTOYOXaoPDbxiaXcSKmsvfTPtboZv0ONS6bO4I2CVZmYoMl2RltO0fEphfB\nnlOEuJd7KBq4URTyrpnFpKrESfXiSVdQsEkN61qEFcA+Lpl4L5ZY7vvNpPH2\nDL/qUrDZrGUnMetm77E7tC7dNTIOUV7jm2EOqHjQ4bG0IqWuHFGRsEpek66m\nRWmjdECaQ2oJTxkpbbdjIq1ocileBuM81oFH2mo4XZ5N2xnpoaSyt8c8QSZm\ndcqgm33uyB6QBaJzuAhKrMsFxVpIl68t0B8OaZ553QVenb/GElrPSEaVecRw\ndW0s\r\n=2nPW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD+CUXfmbqxA8VK8me5c88LFiQwW2hsrH1Sx12vaa7sxAIgVdN8qbO3/7lWsYNjFzM3GRC1RnsoQLICub5ApIMLgVw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.72-alpha.2-sfpresets_1573633065550_0.8171136974389746"},"_hasShrinkwrap":false},"0.12.72-alpha.3-tapestry":{"name":"teambition-sdk","version":"0.12.72-alpha.3-tapestry","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.72-alpha.3-tapestry","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-Lc8SiVcNbEUaAT3r91I7RNwpW9xStCPrevYfcN3kzrgacIVMLXoddsfynpu3VotfAp4kw7849VLwdFyYvN1OYQ==","shasum":"d8cf27c9ad3269dded05897b7979a615172bb6fc","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.72-alpha.3-tapestry.tgz","fileCount":440,"unpackedSize":936473,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdy8gECRA9TVsSAnZWagAAyekP/R3fVRXweNoUYQYNqtZR\nTXmehkZ4QOaFo37VTn+x9dKEdezcw0jKKwYvx6F/FHvvVtxA8OzzvLdrURYl\nCYou3/7Tq3KPAEgPznfdx7OpdPMdATWNnh6cMuO4OzGrzI5Pr6faHZ0DPMkA\ntIOrL0gbKGEp2GYnm/VhNyXzwbFJ4wGwTrb3K4qwdo58JeS2TZmEtlIyawkY\n1EcLiqUx967oqLIw2dNg1uSTUXBBsiKzBWhXJIzFNLXt+cX01JB4bHRMULJ9\nJXckxQWohyoxW/04QQ3G5/8cM7oE1AZOpjXn5IizHBwAgusHRNMy4SZgJe0C\nOsQFmbysnZFnXNSXLa6/Q4BA90heErvZe2aWuUjdE2BZqQU6mUPZfGGDr+6Y\n69qvSyYArJkFTwoKw2b++D78rSqgyk84TXPBKeVTxExfdbHCVtN0dRZivjdR\nkFsmkz4yakF9OcauHncqQ97+gqiLrct2IRS1HZA/LJ+jbhhZCJHzkxwSl6GK\n64C2+wwYrvNV7uQPkzioMzzCEK2VyxVSiOCSgVcKy5Rj7QWbglXJzHe8pMAu\nPNmodqdXlLiJ7jfnbmyq96tGCR/Upt+eCHrkWyXtRFa90L74R/WeeN6+Asnm\n07EwGQ+ejWPQMc3hpjzl0l1gSWpzIbnPKwcAqKXYf21RuCrHnfupvE/U13g3\nZD2t\r\n=zujP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHpmHFAY9CZniFlsSaDBNeeosB5bUBvTe++bh/tzKAqbAiAhcJSwM9U1MzMu6l6ARex1SsRu6lIfwvNJzlIcqUpOPQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.72-alpha.3-tapestry_1573636100001_0.17225976564732948"},"_hasShrinkwrap":false},"0.12.72-alpha.4-tableseethroughsubtasks":{"name":"teambition-sdk","version":"0.12.72-alpha.4-tableseethroughsubtasks","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.72-alpha.4-tableseethroughsubtasks","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-P4yyEhJxZxjpaQz/6UULJfa8uzp77AyWbF4uFcSU47UA3y2zTeCuIXBCjbVMUDoRud90+S4/MPp4JVpHBQiFtQ==","shasum":"9d3b4806f34a796a147899e8351bbd0df6514020","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.72-alpha.4-tableseethroughsubtasks.tgz","fileCount":440,"unpackedSize":936570,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdy8zhCRA9TVsSAnZWagAAFaAQAJmJxMyorqGBppWCb9V8\n6nOJiLY527cQNZw1/3K0lf8IH4ydpMVfCgJG+UNHK3nWwXoAj7ut2z0iSNTR\nUNNX+qyxGxn9TrU64tvz6hm9CeGJO5G+vwJcZlVPATDYN/3jwKBjGaQJnlVn\nNq7nuqDJznlPO7RLff4oYP4NAbwS2m/SJ3141juMw2GF4Va6HTWiXZe9yfc/\nGG4BrCWjKHCBwvX/B1ov9aZlGgjRDr73qCuaL76OzSNscSuThjwHniYZ3pZN\nip4AjUv6phHAPOHP1szYNaeNbiSv5BNsRrSQTJAm9bpXzt2VE9aYHstfsigU\nebrh5pGV/l2+YknHVmiT9pEAmb6ZQAMgyW7oxkfs5TiiWaZHWlCulFJ7Ku+3\n2a9oaumTaT0baALUASh3Y9Dk3jYyOU/NuQYeqdaIuX8ujHl8L6aQPiTBc96w\nO5RFjmQNSMLje2WEkDNGxZvdJ2878nSmu8wlyqj7ZKQ7un1AQFxjCGZpvryi\ntFQdIGvM3hdj0XKprMEhI4H53z9AllRVntBdXm5ZzCt37BW4HJdBvVhFe9bx\ngkjuA4kPDnd2D1WqURz5y/0oZ0ERxJJIXdhxdQMNobh1TP36WaUn9aQBuVKB\npVKarzXZPUiQMPzd24phWV8YCTppLsQ9pPKtnqWOw/NOFhVa51PABmXd3kLL\naqWy\r\n=Qsa+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCcWMbqNvAFu6cwCc6Btwp1rLHIyvvLtQzkQAV61zeiEgIhAIPiOpPvGgOsu4JARFn0E8whb/pI5LWfo7DxW2wKfYMv"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.72-alpha.4-tableseethroughsubtasks_1573637344652_0.4173175973503156"},"_hasShrinkwrap":false},"0.12.72-alpha.5-projtempl":{"name":"teambition-sdk","version":"0.12.72-alpha.5-projtempl","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.72-alpha.5-projtempl","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-Mr4qSFtdW0P4L2qwmJGc0z51CHSlRzVaFTbKjusFzPjpCAr6DA852rg5pD2sbU248DDMqLyaMvHa7YplrJGSDQ==","shasum":"f42363be6ea6e9836da9be97bfb93d031b946b3c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.72-alpha.5-projtempl.tgz","fileCount":440,"unpackedSize":936618,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdy9OqCRA9TVsSAnZWagAAe/oQAJ8xdjLYrPpNQipAqoL1\nrVhYWlCwSQXR4BNLuGYrVlZ0Hp290mK8q8LXSRzKuYbbqLRTpv+bCH0SgI4h\nlGD4n9Eb8DJi9CM8vuU4+35y2QyGarLYlvm19NivD7iF39jRzLunqPCw7oUy\n023gN0tatUm2WQRvItzxVUqaoK59QY8z3mgEtSyF6iZbGvaWwOoZskk8ggF8\nJLwbgd6ojS5llxFAHatRQZ+BCe7mYT5E84NHqwEh8ps/7oFkfbUGt45kSAA+\n6uT7WYBgEjAIheKcW/siQ4nDpFWNM4xv4MLJrDjFC9uLFF5Nf74blvB0ZKPR\nYMKVz08Q3wN37kfu4z2bq+NZvaQYzNFmbwTTbzmQds/7nePX+oTRTq5yfggb\naTMpUUe/rynPWnxVBha99FRtIR37tr2wvOGBcKaB1gEJWXVgRTbKMT1PoqbU\nWYu1pLgY2UXbhDyk5UD7u8JOZxSfI4lRDEfHSPSEPScs0o//DcCjKxVPIvyV\nEsmiYtv4KhxdEDdkSAffaKw7eDB4xlThHEtZ3qszhZViWfH1SrYvFUyZuXVU\nYLo9/vmzW/3NuOOdOQEpjTY0oFs3CPrUemoNY0UFFYy1qAnzxJz+946uBt2p\nHxtQy3Htlr5R76UCmlfyptGrdsbQhDBlvdPiaU8ZsTXq5ZNpP4eKW+7/pxl9\nsJRA\r\n=VH80\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDfsyAoP85UoumKXIaEcir2IbNJr1kgAU46j5s7x7EaIAiEApvVxTGP9nsNpUsXVqYlO34Jkq5yNaVEeAZEkWrrooJ4="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.72-alpha.5-projtempl_1573639081657_0.07643818970767557"},"_hasShrinkwrap":false},"0.12.72-alpha.6-sfpresets":{"name":"teambition-sdk","version":"0.12.72-alpha.6-sfpresets","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.72-alpha.6-sfpresets","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-LL3k5Kk7kHeuLmL16epBl4jWuKvB7YB2NAs57MOAngymUkEM/zhOKI2aAjLrXZ1MFUdeR3ZZIzOOdQ7DLH/q+w==","shasum":"3caca4f6886971027c689efd4571592f36d7b56b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.72-alpha.6-sfpresets.tgz","fileCount":440,"unpackedSize":936732,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdy/akCRA9TVsSAnZWagAArEAP/07fVR5vqBoKp1g3r0ii\nsZslu2Rs5MBg96HAXOzqjr5bA9kqjBSjGKigYgC20Y8RrOeWjaeF6dlrFgB+\nt1+iIRC/d2QDYxkgV5FSVev1UulCNCaGv3nLt31D8+t9biifBh100S9Ti7nb\n3joW8m+zFjMDAGcI40mkNB4URSlOMSuNS0QcfEi5Nd5X8vPuvXyKGIlt/PB2\n/g4py7yx5yiJv0yDwer57bc1gNj9rdvGNni7K3QXDh7cHeecRN/8wYHhzZmL\ngP8x2e4O4vIvtVARo6GHn3q9tr0K3n27ntve0G3kIswGXT8w8Sbe2QTqADOw\nzFPSgDgsoanbgDywJfGIfqwERyHYXEd/1dyiuYvL/nPF1EczJ+n9hRrS3j4C\nFpVQaho+dprsmr1sr2gQ6CYZketD+bL9N/7LvE/O7AsZZGseZKPuN/gZdRk7\npHHUHzvye9xPwat3qRHk77+WQRBnbRTRK7t1dLv0egs1kgAEWi+luyk4iyVV\nfCvoJaQ6xWYvNu4Lr/v1CZT4A4lf6EIveyE664i/EQ8m2zj/5XP3/tGE4Y/G\nTHXbPKxMU5cPfwAUNzzcvF+QSvTgtALEXm1oz9AfdLYqeLqYNgLiqh5j+xQw\nzGqI02v7q5i6r/ID4tY2kVSvxhfyQD5KKZ3sZbTJeaPa1XYqkB5Ou2DyXKFv\nBSie\r\n=d8v1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCyIMsxgWfDiwvOYQiSDfa1x01hbBcUifnyF3C3xhqs5gIgC8Ah4Lf04odSmm8AZo405UieHoVSYnOsxdiWi9a/7+c="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.72-alpha.6-sfpresets_1573648036011_0.1711688144093575"},"_hasShrinkwrap":false},"0.12.72-alpha.7-fetchclient":{"name":"teambition-sdk","version":"0.12.72-alpha.7-fetchclient","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.72-alpha.7-fetchclient","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"dist":{"integrity":"sha512-9jlEgQT9bS7SbAwpOe28WYWN0qAxUiaL38Bvv1VLux7HZIATHVaJhKIIV41ZyrlNfvcKGiMF7zuGBipko9D4Kg==","shasum":"ed988de0a5316b3c94494802d850ea99b6ed6d1f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.72-alpha.7-fetchclient.tgz","fileCount":446,"unpackedSize":944259,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdzPfbCRA9TVsSAnZWagAACucP/29Kmbm6vXuTW8O0WNZx\n3s2ot2PjVtFHZB7PdVfOcd8MT69Js0z5FRQKsMcVQDooW1+yYV8BlYaPK6ma\n+MHuLmj//6ISLoQzUttjR59ZChNgaSvqayfoJ21BdDNRwp1ltFfBLSXEtHHV\nMsXd9TUKufZZ4C/85yo7Po31pzHkl2M0nQSQQh5l+dbu3gnaNLu13139XgLq\n1ZSZG4Kjm4g1h2+LYJi89dZh/fwOeJsXExt1AooJd1dbhtnfxMvd+gIup1Rm\ncUMaPl8kWGchNXczgiAbAxf97Rs5SyEBCMcHGd9Gy0JO+k/9pk1adQVtzc4g\nAvMqR67BqFDFcqsnbUAePVEwc/OMNk9NVxECUHoSnihnNOrDEtBLB4FQcgEL\nqsKQzZRg0xK31lSB3zx9NHCkUKlyWJzPhe2Z0n4chockmVSER7OqV/O64h9X\n/Z/0PrH3mGJFC+/h2l4FlNRW5yHrWKf4uJ6FwbDQKNcgJ6INrfCzmw6tJThV\nUeLr2u84TXa45IHTla9YOhY/3pOb7VypFNvk7U2tR/5gx4PQfLcniooMnyDk\nrOHH6W377UUXoSwRlm9ttuPUrCOyFsoJgSvcXKDzU9hDo94G2wIIQmqAo30E\nGAsSTPEkffHeHHo7z2d5gFT1dp6xlrDi4jI+ZXzRb9xSCqHIdYmp+wC9uvxm\nHCJ4\r\n=+xoH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICc0pn16aPaiNyYs170aHvEYaHhYHfZD3ceAfP9LrdnXAiATCECWrpOhi1McZE8TrfxYze7kiZmQKpsD3IPiw8+SUA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.72-alpha.7-fetchclient_1573713883280_0.7458939649340512"},"_hasShrinkwrap":false},"0.12.72-alpha.9-batch":{"name":"teambition-sdk","version":"0.12.72-alpha.9-batch","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.72-alpha.9-batch","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-kvkcF8R5QtT1Hd37G03fiv2FhovavDm9/NOWHxLaFnBxdnMr2HoENPSnnzdqlfbubErz03cp9AncwI6RcgA8DA==","shasum":"78e3b9b0ad4c060f4a059eadef8b8a0be98454cd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.72-alpha.9-batch.tgz","fileCount":443,"unpackedSize":955321,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd049uCRA9TVsSAnZWagAA8wgP/0kCnOEnth0HbW1NnvAS\n3l18Pr8Xtue9qNhr+zbXvngIGdqyB+qVxNJQ6tPxt9a+Qc7e3UrzHzTSQBr8\nyjDk/OQ1rM+S6AVwakVQUPEUuRnmJNdkv0xG/9rlzAtrEd6WVvmwEoL/Bqex\nOGhRDWBbP6d0UD+53gJy45NUU7mXGd19ZE5ISjtejmi0eaKmHEidSZBw/QJm\n0sOGLlGePCS45HXxcWp4QnjzY/3mEM4q38JgoX+n/tq63kCNBd9bKH0FHoyg\nl/JhO6Fnl48J/deeOZjcLiN2uZNwHV7ClrdyCJMYvf4D8PiN58Ndn4ToTCUl\nxSQVqBc6SKZA3d2Z6c0jEe5IQkgjy1Ffi4cmoxR6zI93dnHFDZHZJnv1787K\nbvodvaWvzaAY870Y72YNyXkC/gHH+diabEUjkItsEQTElslD8Jhd1aKSVZoZ\nKFFuIrlzkXl8QoErwHuuDm/vRBNMwBk067x2/CgeMmsmDkqI+PjJZTe1oVBr\nOD/JB4xCxwZ4bmKteaU2/DVONi103TTnXK7H2EWvBt87coKro9fHayOm/eoe\n571iQbFsBlINf8a1cD4m+CbjJkIw4JCaXEJqKUSes+HDDfrNGNb/kcJSxc5V\nVc8pPCd7C7Y+UkJovITvhAE9uTBlbk3TvxHyfMrcEjRiD/jfcZce/37eBvXE\njbj4\r\n=ZUvF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA8lQ4AlpGk+0cxgOno4iKmNC1CFfVCdYGKEhIZsS+JiAiAHRvx/HXkpqo8oinaknF9j64Pu3xY12rqtrs4jL7YVfg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.72-alpha.9-batch_1574145902139_0.17147329403247946"},"_hasShrinkwrap":false},"0.12.72-alpha.10-unftitle":{"name":"teambition-sdk","version":"0.12.72-alpha.10-unftitle","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.72-alpha.10-unftitle","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-XKqZtggGkmWyeZyKzABa54u+iM8Chl0pMusIG6HvPkGABk95Q/Nd+aAUJBw8/+c135u9+bRRjJ6AzqyhI7BxRw==","shasum":"32661be2c340e4eef1c251d4c1b8ed74a5f6388a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.72-alpha.10-unftitle.tgz","fileCount":440,"unpackedSize":936813,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd1OsgCRA9TVsSAnZWagAAc84P/1qLznxdQ0eHs11fDhe4\nZ9H5I1cQHwgCxNnEmb4R1ubyQwAbtrW6eBqbjoU0BMedf00KySnIFEC04mVT\nkUuLEzpYPJzApaBy5mhnNRHSO3s5eFh7Hgo+cwUM3y7ZUmOFGf2SAuCqsPN9\n7xAz7hmyLi2h5r3z/IGGiTR1x35+G6O/1ooqpRxn7mhVZxcTvYT3cxZyUEqp\nzRBO8Lx4A7PyNYJ8ZE3ck/2NDVakkPgjYCFTB75mWMsKgVwXWbnrArnbWYPp\nWu1CtW8+NtFSm4h5drHBJjt+hpxUpkpENa/Uc27hDCGJqg2Tv/2J+jJZlTS6\nIFEqhudxP9HxxbM3vm7ZfEwI+IjwTWk6IayOamBbfnMalpWU8X1x3ie5DY9R\n+cPzTkuhCuK8LcI2bwbBWIEXWibmh9y8/dFGFDNd/zE9GKtdMZ97SVeHBk6t\nfoZJvmuvAbZyCRJi6EDIxut1xII98ZRoXcZJAD/TFVRtnYGqWg4AVOhPLCbh\nrn4fhKt03ZRYtWy1K946GsPbSD51Cix1Yxve+VJThbFnxc7n3WRRefyZsRa5\nMcmSPuU9J6OCWdCN0jxdMzr5hfuHmyJ7Q52lyGQgyJM3eZTeXxWacoTQ1+ap\n+yU1G7YEm6W3okjR81ZiiN92+76WWbuHGP+Of2USRLio7SInzn/hhx/6e6ZB\na3YH\r\n=+g1W\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF3z4is7uxwUWOLE6U2DbDwS77Au/QAM4EeQCLYS+dZXAiAlb0dz+Pzjrg+z9AD+ya8TjLOvUNOmojSjntij7beMww=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.72-alpha.10-unftitle_1574234912260_0.6758980872967932"},"_hasShrinkwrap":false},"0.12.72":{"name":"teambition-sdk","version":"0.12.72","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.72","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-EaGcU0LetZyee0PZET5Cttlb0Q+dzuQxGOKZSfvOuj51xkOAgzMgEBFFBO2+ry7AolJR25nxUgw90yK4F+zyug==","shasum":"ab5c5461314fb288b30585592c313e8676a90eaf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.72.tgz","fileCount":440,"unpackedSize":936795,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd3lZFCRA9TVsSAnZWagAA50MP/29Q73EjAPPO1E2vVmn7\nVtGJf34+ZOHvLd+yfCtyNrQhxi8iXO96Hn1tjhDn0SNFc02zTyWaWowffygR\nK1nXFms4ZjagWKxVKCeRdUVcIQ1FZTRIdBEqZ4kktdLX1H+ovN3XDL0HeEkV\nMXaGPbT7QCTTxoreWgF4ZOph/pgY15UzlRTM6MpMZ77ssufSLEBl5+TRxt1t\nER4ug+knfcq+t6WI6ExAZ9c6t7g58vZaX4V4DQuEs+gJp+KXjrh9b8/a3lHK\nc0h6iexk6YNzzSJvXoBApXsI4EPEP2g2EtOh60tGH1etpM68gMZXMYj3pmlk\ndLxtJuYSznGOWW0h6mGAxEyTSEzTBmI5emsoZLpvfPhmjq8aA5VpDSUo8d7F\n4ONRV3iSjEfFTrefU9FsbKpRvXJCJ8ho4oDFkfg2tkG31WaY4MyAbdnZpLNJ\nucbHrJvKczlohw2ZzYrPPJC7XauEbAqHNlf6F10HA5jgpWKXQgU0RNpX1dBm\nI+46MwGe8RYzgz3OSQ0ZVLqAlhREbcaH5VZE0AvRvxMQMkM8AgZIo3E7rLTM\nsnRcvI9zsKxGXw2P+JfMPGiSrKAmDTcJakt9TiVlXBX55k7AYQ65NukKCfOW\nJ6vqc7ZjLyEIcYLDLWTxoyLQik9IU1nJmwM+UEpEuLC6C15VLdf33nphkV4w\nhIWY\r\n=sTTL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDy7STVAZQLgxpnRsYv3XiXxXp1CucyEpXHQH5XCfFXbAiBbfVoo7NGqmeqp87J0opTobb8CFJhETycXbTd1YlTHGQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.72_1574852164716_0.6260730616702321"},"_hasShrinkwrap":false},"0.12.73-alpha.0-batch":{"name":"teambition-sdk","version":"0.12.73-alpha.0-batch","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.0-batch","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-/sMWzN3NjXHuEgTg5jbuQYGRw8isGHO19eID76qKegb800owvtotloPxfY632w600tx8i3ndq8ym7rp3R/1dcA==","shasum":"6b77839824f1e98462e89b71c8aa4f07b0ae6c53","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.0-batch.tgz","fileCount":443,"unpackedSize":955402,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd3lcPCRA9TVsSAnZWagAATbIP/jZH0BgDV2f/TsFHjXwM\nIsVBEH9GTjjWrvrrGMUyOm2dvYZog6Mq24ejN+DZU4WRlZetoIE4SfcvHeep\nyZUDF21WqynJf2/E3BgvagD+S2lao4LOu8kqfZphTMQRJ6049qUsEaByFVAJ\nZFXHb1nDMhTAJLkx+8O7IXxRPYmQsB66z8D/y+oi4M+PEFuOpzRNgHEHVNF9\nFQXcPD4tRn6IEDnMrA2/9WUuX40cvkOGFnfD9vE+8iQ/qD3LiPMBGbVvIG6k\nuh2lcgT8NvOTfLaAOZh1w/CAzKsEWoBDDtgT4TvRrTLCtLR6C4DUidX/LNAl\nbUIwHiz461k/MYm738QqwNL/djv5bjbwYzkqwNOs1GIYMbpuENH6gtVwQWrK\nn3pKzAoP8iPcBUrjc1KK2k97SE3zrRCvZ34Kt3AqEg/ujT/tiUQg3+j2fWyJ\nCov5cWT+ycWCBS4MTeze6N2VIzWyxmEJNHbEjMHoUoSdKHZbMzu36ruojVlM\n5TyQdL+FBX3aRQOK5ZFOq8p5f61a6M2ykiVYy3HJS643miWeo5kek/prEL+e\nY0cveVoJS/PQTkrAsT2hVOA1Z6th7st4BFp9bGehkh8tRI48Tk8dw7bn8huL\ntflE+ess2CKFFTzzwo1fFNU5rQZB2HGDSeHom/TPpkh+K/GcUAMfqtGFqzJn\n+msl\r\n=bLuD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCFjYo6SsKoOB64JYG9m9SV9Vef9FWuwYoXic7+d3r2VgIhALDm3iviU7GeuNVHg4jzzAuNF4TitpsV7UUo4YpW2oD/"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.0-batch_1574852366653_0.33895396663977784"},"_hasShrinkwrap":false},"0.12.73-alpha.1-setHttpMethod":{"name":"teambition-sdk","version":"0.12.73-alpha.1-setHttpMethod","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.1-setHttpMethod","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"dist":{"integrity":"sha512-FBQUUveb6fTtO5fnIdO937fy5wwM/lAuVP2g9FVrLF+vr3cDSMLyIKvbWz3OEK827axm5pHbqpGXerfRAED9hw==","shasum":"9ffd9156a200ea0d01621389e6a25547b134fccc","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.1-setHttpMethod.tgz","fileCount":440,"unpackedSize":937926,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd32VBCRA9TVsSAnZWagAA6CcQAKOKyCaIF/ZSG9ZSeCq8\nzlEqGwwFn5LYuHNJwI+5Ha6DVNYQj6TEh68hmoEi6u6rPOm7CO78/HNy5vrX\nWOWk3tjIh+k/H9dsAcqfDzgshbEyDtkYZvquex3Ku42yARhkThIpLpoTrQj3\nbm4w5saEyQxeirQbhdR2IRHV3vcXPMn/NRLtqbX05MZng5W+bLHH2uCDwj0M\nsKrxE/EpCvojwf2jJGTrhfcMSiik3z58FKwiceM+JPDCz0XmrjhznpNPlDvH\n4j3QyFB7T2E2ZVEnuK0xsKxN2TaFPFELofVJtpB7Bel/tY9SII4QiJ1Bhmbm\ng0wFjqLoLNNivYpg5bLFATwPF4AuuIX+zz0E83hBCM2rq8GzLerxYwar/ktm\n0pe4FwzQedXk+oAlEcElW0v7tFGR1LyNmPbV4+kcybL24b6RCfUBrHrO2eqe\nCDj0zD0UXTmXRyX+tMiocE+mcYUXUVczUrqsBcRE9j5kqOJ3ZIQFrzdyUoQH\nhQ32TtV9mE4UNpKm49AoeBEywhjW0+MDiwdaZJAKQBKEiHfAdvecMx01u5DK\n1kfHvfxA5AZ2I8b1w5xcekghu+TuG3ZewTjMPImFV8ZPgVQyssQ21JNS+x71\ngnTO+6G6FvhLRq78irMs29DtjbMUPrl0vM6KCYXrJOn9yyZk9pHJsTGVRwzK\nNUjm\r\n=4RdV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG96G4lHwUSR5tsZBZo0L3tSeTZF2pzJWtfCgirhaalFAiBov5vqgW7j+yeRaZJMQb8S6ZM/sYFL8DQFQW1O7gs6vg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.1-setHttpMethod_1574921537253_0.3232111413968599"},"_hasShrinkwrap":false},"0.12.73-alpha.2-assignlinks":{"name":"teambition-sdk","version":"0.12.73-alpha.2-assignlinks","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.2-assignlinks","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-Q1UnGohYsX29nRkahYwdqS2EahbNsojQrZTJdvn9H2HCo2n9eaq0aDReGiK37d4TKR8YO1wwMiHOzIsA+r2J1A==","shasum":"0ccb5983b0c10769d61b2fc95384167f18e6476b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.2-assignlinks.tgz","fileCount":458,"unpackedSize":952496,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd6jE+CRA9TVsSAnZWagAAsdYP+wX1WPPEnhJ0i9msFz4S\n9nhXJBqmksJM7/vGJfwEYbRfKrYiYSGPeV8kaIf4IpHLjqTVp506vUuol6X1\nTu+K2D5d9XAn/EKIwWFDDhOgIn/hMU6AiGqS+A0JbVrhIX8IBUOQuz/yHb4V\n4sByOgZN2OaPxGoU1xNsFOJNvzn8X2dUZ89DCP/EqDPl8ZsEENoIJd6fqc5l\nt5xYQZXgfQ0TYzaZjFkDfYf3QOy3uMcn7jmfNhersI/5N7ZYmlo3WchwJ+e8\nzzHkwZkiFjb5Pwpo4+auc8/u/fYJS8MQa8lPfRHsH0Y5MdsdSlzctbGfb+OE\n/dPhIi49chWNEae7Ck/8M8KZDIV0vgur1l8jxrcBreD7AS4VHDtmPhzLZk6A\n4VqFpSeW/bwr+/xvBeKwn6CrkBcqrd6XovQi/wcBBZEiR1kS0pDIrPMtGM93\nHvNeQy6XmwukTTIKcrvyK5SWcHRcuJkuGnEaz8dwVkJYlfLKEkz5ddy0DFvz\n0k9r5W7cx24gaqbMw97Y8mg+j1JRwx8cG2Bv0uqQr+0GrR6j2LNYxlFJBXtR\nQWy1oKynStG7Nkl94/B97JLvYqie20VkHwQfdnVL5/wEBd8wOVsA2Qc7/MyD\nc5BWmd5+pyRxeBJ+4jlS03RAkjeiFcEpJr1JfmaL1V4FJZ1Uc7R7kwKFk2BB\nytIM\r\n=HTmz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEjgkXbInLtxtE/IwN2LmSSTI3eY0VJqY0qFzWtyPZIxAiEAqayRR2vg+nzdDTg8EoO6UNB9FhVdwYsiEFsQKvLsqgM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.2-assignlinks_1575629117984_0.5136566164261485"},"_hasShrinkwrap":false},"0.12.73-alpha.3-axistype":{"name":"teambition-sdk","version":"0.12.73-alpha.3-axistype","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.3-axistype","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-aWgFhkNKTmlRRwkyvM7bIRLylEyes43aZLp2DFogYd8oFAdkvGiE5mRz43jkOqBW+GD/MPVDVj1bn5rUyZRLPA==","shasum":"c3c0ab7dda76a11ee90e8b85f179241bd7f43511","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.3-axistype.tgz","fileCount":440,"unpackedSize":936891,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd7J+bCRA9TVsSAnZWagAAzYsQAJWQm9BMBVRXsQRwsZ3A\nYNWzWw6E2z3FYM5n9acARBBOrHLMTon6CjD+aik33Ap8Q7de2ABHhqTEfUqz\nGqai3QhjsQhoXkbmDqhI48PBqu6WFe2KXQ/E3wdbaAC0UU++ODKSvekJWLDX\ndMPE0bBhRrh8n8kPaj7KhqsdRgSxpxdkrj5VHZgayKOR6YwbFQ2lrwpbtHAB\n/isAOsXG5Xma/Ui5KZv2jCYNftNMdpwaCvJmfDd23Or4oF+nBzEzcw9vGWQJ\nSskamhiMTRtin/J3mpUy424qnVHbT5+sbJ9wMTOD4fC+VkCOl8dV0OMbBkvr\nBtTYZAEYDtecSrpfonM0M7BgNkLFqbOWj41nUjlGzoVDNolFsA+oYALU0bSE\nB00sFil3HdiGZS5EYGnGPRbTVcPlyCbtBORw41rab5YZyMSy3QY6zvzx41u/\nDylOzDCDe11PZHA8/5XB2Qv4QDr6igtCw78siUKlbtHmTL2FswDK/awVA9H1\ngBCgLyfx9ty04W/L73d9qv3+QXINmJXHoo5rNFWozVQQGPmje+8KT2P910kH\nRuRCwCjqTuT8twRSKUFvlivrnS4zZVfFyNuF1xBQmbrVWxiz4b4HnSvJREoP\n9X9hLIGS+cHMdcJ4OmJMDDpp76q7Nh+CUZSNYw0el2SkEPHh1+wJYwZgb77C\n43QG\r\n=d4dd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD9AiVVfpTOL42O3CNaGElPTkyzu1Q604hNUDbypH5OuQIgbhIq6f1BmqTSRweiFl1TCFi6QuHAzLGti4TTw3ulSK0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.3-axistype_1575788443299_0.49346478272832717"},"_hasShrinkwrap":false},"0.12.73-alpha.4-assignment":{"name":"teambition-sdk","version":"0.12.73-alpha.4-assignment","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.4-assignment","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-tbkMOC5ianpwpciTOOTpfqVpLSpvcT011lnVUJdEKXPJMdqrqhwjQl7ACGWGDTo5YJkojO43AJJG56zBocfHsg==","shasum":"5e1649de012f79f13a9fd487413b533d77aa9f07","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.4-assignment.tgz","fileCount":458,"unpackedSize":952495,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd7bjTCRA9TVsSAnZWagAA2FEP/3DmNMs9A6pxmoViprIl\n1lHJu+qFCIHcgPJ/EcKFlnw5GFUosprKP0bBYnh4FIhTT52UdnyEbvI/QecO\nTbmpfT1Sy3PClIENw0XHGZU0KgXVC7i9z4QcQu4g+RsdAuECFkiI5v6jUffL\nnxQNPS6vkbMxDKK8UAykydZcNpQypOeR0VPonnvBtP2yGf67dfw1vzUWeW3W\nuohxOw2KAKwXpusad+4CU1Y54U5HmYFVswaib/IlTWgZwHadfv25BaxRUOZ3\npZEtGV1nHbdOIMRftkUPHy7UWhJLot6lZAcScJLVksP1fn+ePKpziQGXTGjo\nplsrKIxlJEYm8CYdcwEnHXZBV6wFOpasCFCG6yphJkb9FsKtbyR6YVF9yhgw\nfQnM/BAu8cACIklBvsg7IQXou/nx0RJeCsncYXF1d2288VqG9hTwlboz+GM9\nJby9zGs+PZYXVOJbr8FAbA6HFg2V9H/cpOGypnklyvtW+EMI3iqIkm0o2BwM\n2DiR7U8PwDhv5PGzx0JdwiA52/qA2kiyzi+3UDdWb8ZbjjAHh/u1KcWoA13L\njdCW2IJkom+vLcwTOhesywkkq38612OHdYrAyGFyy4AU3xIatbuD4xxM6jnk\nkNXs1Twxux4tSahE/sJzn36y8bk47sNbM3w9occc698gCRWqXxl3C+A0voFV\nWqsy\r\n=QjsR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEh6Tm+cfindRaq4KBisON/ICdTqirTunDY9ke8FjftjAiEAsCLmJP9S0GMMJEoxe6AlbyDdh7FS1Y7x+jICMlf1f/M="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.4-assignment_1575860435254_0.1745829789232931"},"_hasShrinkwrap":false},"0.12.73-alpha.5-assignment":{"name":"teambition-sdk","version":"0.12.73-alpha.5-assignment","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.5-assignment","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-l5H80SbWbXLwBR+K0G5cDk1/k3+sdjoF5Q5TuwQB8rTOiQqlqqiPue512lTPIWE39fgfasrzRV09dYHp2eQy6g==","shasum":"55ba605152ee0145568b152049dc6c5ffda237b7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.5-assignment.tgz","fileCount":458,"unpackedSize":952372,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd7cbxCRA9TVsSAnZWagAAff4P/R4tIJEsOfXoBXNt4HuU\nnEnYb7O4Q0E3LrXSwL5gCQMvGl3g58jPwNMjZ/eNYKJmtCekHce2YzaqiLTa\nMLhJEzrDIuBfpXTq5TKY4oB1qxjyrsOzCoBA7xGJtq1XXfiDhsKh31H4u0Dg\nX9KgH+ZdXZkc8gd0R9tPL5hBK9nO2a73rOBLWfqdZgxCV0GiOwKZeVGBZ9Df\nerte5mug/lP1Vn0BvJ8nofO80pDPYUBcNzfMHh8o47zGcNaL2J6fRV61pbRK\nagTmIjdQE4bPGkEc1XHJF++dPlNU/l2l6n+GfOz76nIRlLM6hbo3KE0a26WU\nlKvj+7zJLJlv+AgJaEmXhLNhh+d8TtNuuD2Ct4sLXxmq4QOjo1j4urwH0DZt\n0QQ2U3ffxfVF5XBJmgedVuV7kj1YhwevsjR92XXwMWGaRs04j2s3z6Fx3iUV\noalGjOlr5KLfABQ7LOsccM0rAVAGEWqdtc9qJgMP2biYAskrWjSXv4qtwIyD\nYibEl/zNWavSZmeZX/121jIsvcsA34pXLOep77uVhQJHCip3ztKzl7g2pP39\nHR2Wmp5m8PAZGPX7RzdbLUEZNpFu6Lu/oXYmn3QVoPXS6pSGkZPuLrbKspML\nYURC0UmD+GbJhYVBC/AA0+cuO8PgD0xyahxxPI0gEFMqzZ6ir+n1jkJiVV4s\n4dXW\r\n=jbNS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC5EFeuO7nYeqBmCmR3dOq/5eVRVXsOAti52RqfMuL4jgIgJOJWiMLdCVHHNfWnpZqTKIyVPbSJKtFnJe1FT80ER4c="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.5-assignment_1575864048927_0.8482982969172792"},"_hasShrinkwrap":false},"0.12.73-alpha.6-assignment":{"name":"teambition-sdk","version":"0.12.73-alpha.6-assignment","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.6-assignment","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-Tkruj7xxRdnd/iN4u8UYH2L/+MHWPCADTxO9H8ue1KyHQMTSjydesBZt81oe6zmIcTxycO3slx9nNFpDXHApCQ==","shasum":"45fda6902f4ad86412440482cca0c313d280648a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.6-assignment.tgz","fileCount":458,"unpackedSize":957014,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd7wB4CRA9TVsSAnZWagAA+4EP/29oXqeTwyhtJYvdAcIz\najmhRisV/CiTCt8olyOaPBBs8yUuMo4baYR3dEXFihyfPCRjQA//In1MbZVi\n4r1QCqikeofqeAedGD4tGbAYy9w/2AqbSfvI5QzA9Hpu6GdEnkZuqZLZxo4O\nTlVoCcMk6RqMf6TpGhiCFb9KOYJXWE8rxhQAR1Zj0rWYJXoAbYJQMkAL4mVM\nMPY2ipVZ5NP4X7fU/AjC5LzQIUVmMd2V661YMDb+HU5Xx7zGsky5PjxEF6O5\nIQaK3ToVgdPM2rqhaA3vN4swTBv3yiTUXRhsGdYkma/bYlJpQnJsXfMNbiAS\nYz0czrgGdTnra6EVl/vjauMZCd8bqVtiPNAOc1oY4IzwM6GL+GVJYAx7yciv\nyUT+FHyUFH+vCoJmBqLOriBpWtldOKMGxV5OQEIwFPPra+DZz6hKPpsM7L6g\n9zEes5lgTuxyRgQCExPG2rBHzDPIUmasTrb3O8r7HOSBnBoXrGTPBwsw0yZq\nLfTSc66HqIONWR4ASkFniPtj3SzHPgPshd+AWxWoJFX4tS4tO/w2hWYx45iJ\n6gikSvZCDBaNnOYjhT1a61D1zs4utRac9ymVfTfMs60DD9JETu8m8oDsmSuu\nqCsMX3bWAzjbAYbMRnSo9vVpYSYcqCaNHfYtkOtgQkvKcpK3Z6AZc9tFnsAd\nPdcy\r\n=Lk35\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBHBs8D0EkP7YnZNwB6bFFPhjluhW3qkn7GR2ZXzd5WWAiEA30cjBVJyvHjSyOGekz+oN3+ohjaJZbhH7kOv10V87AA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.6-assignment_1575944311552_0.293287083174703"},"_hasShrinkwrap":false},"0.12.73-alpha.7-lagtime":{"name":"teambition-sdk","version":"0.12.73-alpha.7-lagtime","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.7-lagtime","_nodeVersion":"10.16.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-Cm1MuUDWHFU6VohRKMSTLSstHoAlww2Lo3wIdpVvShIhO/M10Nl+V3rOfDBBS4ADN1V4P38wd6lNiRcCq/JG6w==","shasum":"449d5b44c33383ba8a66a79051cba3d1c46668fd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.7-lagtime.tgz","fileCount":440,"unpackedSize":937006,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd72pgCRA9TVsSAnZWagAAcMQQAJIME40X7N1zsWCJKj7l\nCIYVfYG86Fe5sPEcQFiuFTlHexUcGprHP2duLG282d9Z4nshZE6XVCp5T+29\npbyOKyJs/vGQ0vjds7Juin7EdfQh6QiomiLgGdTlUCO4NSCEaDK57EydsWLc\njRn3Ct67AXwIKL5zFYoYlvwxRlvXoL87Z2/RkbDWmkIV8f2/SfF35A8OMbmQ\nJupbJZfIQwHkNTI7cVuXkl7q3/UBsBZX0+1TR/+SsQIe5Uq7bfX4d+BECXnw\nKDu8vZUHSI54ELWsH+eTFuOWP8dHzA16MsA0a4e+eoYjHxU9Tw+pZhMeLI8W\nrjOhJZOex46pXp0WiB55aaO2ESjLUwU8D+4iFz3rZ5YzcsL0DPahZlKHud0c\nRMCdps/dd1zelx21egMLnLR51Bi8S04YTr43fW72S5yWj3wwPADK2jM6i5E4\nRFpLaz0XfMz/n+rXaVd6NiinrlBq8YL5c+QNiWUk2utDRh5h2hVUPimj4X3+\nmzFkaT5zDa3DcXWUoQdWaMCm/fflFWQ1NBi5FX1wOr5zqcRZx44tAmDwNkQI\n+bNdTi2p9IeqOm/6/+H/yAciBxfKlXZuqhU3MNWjeMmFGjq9WJczUw3WHFkA\nZTMZErnv1PJl3J3FGfUHkvhu7I+T1SNTDdmZfyUYMUSluJOufzaJIIAYrJhT\nlH0x\r\n=CTv1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHSYu9Ifo0da7VY3SDWD3/KKX/Sebb6Y/+RXwM4ure+jAiEA5EbJHFq+Q1A0k7YX5KHg9iRhmkA1wp+kq6HMQCPSk2k="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"tb-web","email":"web@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.7-lagtime_1575971424442_0.8275409368568256"},"_hasShrinkwrap":false},"0.12.73-alpha.8-flowstatus":{"name":"teambition-sdk","version":"0.12.73-alpha.8-flowstatus","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.8-flowstatus","_nodeVersion":"10.16.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-sDNKY74oDN5ppR0xoaKPKmZnhh2TNMbdjZZI9rDzrdd/BKnAAqhLJor3+QpXzZsydgSN9w+RxJTiUEfHrDArOQ==","shasum":"5c3c06c9b201c2ff39986f46013fbde127a07ae9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.8-flowstatus.tgz","fileCount":440,"unpackedSize":937078,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd8GrTCRA9TVsSAnZWagAAkyIP/jgexe1Sfc+C5w/mFFzb\nYl9ATSXezyecg64xN+rRHFUn/77gCP3uR+okUDAKKHCzXwcBKYUGdxf2z9bu\ncBqcEKZ0vx24ZJrNDnclChQVQD79SqqGqNQPntHq+els2D+dzwxCeiLMDTSd\nYvn4/RMuirqR8chyzOdY6uM4L/YQIEJr+hPEjUu8t4an159vybb7CTBZTSvy\n1hOi5f+ITmNIqDUES6kdXZMtIRgV4vfi0bRsMBby1lnvpAF0Bm7RnjfNieSj\n3ehFfaljtx7v4+nW/frE5S0kImA+qBPYgl8hsp3DOYRK8nMfmOQe7PqCdl7M\nQE0HZ7FI5BVhJeuEqNIyuJbOT+gnKmVlU5k1E0Mqs5ZCYtEUbZCunyKAxmeB\nwgqAfU/v4f3DkCk/qxfd2XDwJspxURoTOuLyLNVfqB522Vt2MAJKQjACuw2U\ncRyUFqk0nFTcpCHKEWt47Skzczk6BmbD0n0oolm26N4G0BtLICxIqhMDDO9K\nY12LY6+++hGu8qZMarl+LUkHhtI3e2cWbxXNMpgBIvUd7q5yweT3tB8n1RS7\n6AT1eVeSdFyvaACrkYsSqqICXfFvJhyjuIlXmXBeRmXS836a0EIPl2iOBmvw\nY9FQ3QBgjd4Em3Qp1Kz0cGWBQPVNxgYRM3ISSUdZP3W+H8fiB+ls6rxuhvfd\nUTzg\r\n=qgkj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDc6Y9VwUeSMNAKw45lI7J27OsthZSr5Vh/e6G41SQTmwIgPz46s9sxVZhMaCgETeePSb/BVNAR13S1+0p4+H4a7Bc="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"tb-web","email":"web@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.8-flowstatus_1576037075262_0.2656454054958002"},"_hasShrinkwrap":false},"0.12.73-alpha.9-flowstatus":{"name":"teambition-sdk","version":"0.12.73-alpha.9-flowstatus","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.9-flowstatus","_nodeVersion":"10.16.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-ugrOeCdyk7VT8xfaka8cwqpiFLoBNbgs2cJHvd9cPrNoXRylY69F1quFxWWr+5El+ZX8O+HvsFC7ZHyVQRjeiQ==","shasum":"77fd55382337d95f68eea3925fae9665e8eaf8fb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.9-flowstatus.tgz","fileCount":440,"unpackedSize":937181,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd8JuQCRA9TVsSAnZWagAA7UgQAJb8Hu0aHZ88eNGJPZFe\naHypoV64Yg4EnE+NHJpSazrktmRT+i9UiC2XDB+h9AFtmTuEpa8+yqGkfLeI\n3uwlA8fJc5TkYe3pPk5v9JGkm50L8oMADXOtsFp1FOjgM0HAY/K5RPXWNcGC\n87+h9vVZ3H1rblh4o0hDxx5ztLTSOR0yg09zLNEMqAIUPjO5+fpUJud3cVpE\nWhvCWKuuYoA8jdK8MGJITdi3Oaj0WctcKTnQgzwApQjsCqg2j36xrNqt9X4P\n5x0B17jpX5GtmTX6bOxvSO0i/O+xnrHKeSdR7um19YjQFD+ITIOJSfpJl3s3\n6fkyZN/D4oCN3QuwB6zJklw12VkqX3U4SXjzo25dm+ppsCNEcLmjRolkwuy0\n/Akg1fkm+S+NPZ+TGmIS0vl6lSK3eQRLEi5BUIzTeKE8ZMbBpZFuFLwL+X4y\n1747ivDQPBN5HC4Y0lmUzhRy4iWqtomnxbKms/g5jh3DLv3Jp2NkcYGHOx3u\nlhnAHWuHm7JySGNvEZ7CsW3dzhvgy+rwiLtc/MQwaiRlHMpw1cu5RYPwJE5x\nI/vy7NBDosQblbQxXHsb+DnxZV1IHc8j14lfll8HFgbnc+hZ4Mcn4sykwiIh\n+ojROB0Ew6SYjQLcYNshil5EIX0FJFxWRGMGS3eYHHUWZM1xHYz1EKKpIFtY\nmVHb\r\n=mrKk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCfMgOpB3Jnntn0Eb+0b/bw7SQ08HFqzdPP2mVVBcMevQIhALztFbuZ1sOS9ygIyZpXMVlJN0pvTMOA0fVIHyNstRm3"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"tb-web","email":"web@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.9-flowstatus_1576049551951_0.25173964823819617"},"_hasShrinkwrap":false},"0.12.73-alpha.10-priority":{"name":"teambition-sdk","version":"0.12.73-alpha.10-priority","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.10-priority","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-i86nxo4DuDmqeoc/kAo0JSv5MK5jCUxUbVt9AqTcOeSUFySu/fTIJ+jsWM1YcKWM4J80pgI2jXDvswsYChCM2w==","shasum":"4086fce0ac1cd2ee457bde365bbde728d48f283f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.10-priority.tgz","fileCount":440,"unpackedSize":937089,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd8bhBCRA9TVsSAnZWagAAZLcP/0a4UPj75TKRUpM1VcAE\nSPLKfx58Uvovy3cIHYNJIIzcr408M5z5CmDthp/2rf9ueWvgAu0EAB8ejY8m\nVCk9bCMF34gIxFEMcmdm6A5ot03CckVmqp0Kab44ZvvsNW15G5EzFqzcaI+I\nJg1BZmmFv9UdGWQXtjKGmKaQpqBI8jsIx9A2IciZ5xGb/7Cgregn2Qng9VSY\nmk4xwmRpEu5ZdIcI3bwLXtcWbGx8wDl0NF4SuqGRpVPLkch3wnXzbE4tFya+\n/8UGDmiYST/nGfudTgKkiHu3LTG1AGGOx0ObIrP5C6CPkmqmHbBQWmdvZMS2\neuw5N0PqH+7UWtaliI44JTSXCY5B+2nj1/23FRxXx4gJBfIUVQSIvVQi3ObO\n+wTz7dOxNK93esjt195D1UmY8cGvkT5z38Y0rQSITJq1N7JnolyTkPQgBurs\nsN35ioqgwTc6nWuF4CvwCHaW+HS4CDPYhZQG+wYBHziVa5lGrXavEjLPxGUP\nBqyjtzhrwqGnKlvEl7f6lUk79ItMdUb+GuDW0KOshzRaVh3+wmqcw+vtSgpF\nTufqmv+n4yAKvoh1QCYfi0+/daUOve9pP90yDSQtcVEUqftnMLu9FjKsa8Ch\nIfgu5Q6WmXlmAWZOJ/pqX9XtAvsuOFQE2hch5fMCrlkiMaViE9QimyM+AVHT\nT/+z\r\n=mfIG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDaJWwh+adi2/pImQtBgKU6bspcttKZQJIOeIlTyLaRGwIgemTcSwhdRp4KDl7DDE4zJS8m8+DPSa1ursyghT+zNNQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.10-priority_1576122433353_0.40957247964815857"},"_hasShrinkwrap":false},"0.12.73-alpha.11-milestone":{"name":"teambition-sdk","version":"0.12.73-alpha.11-milestone","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.11-milestone","_nodeVersion":"10.16.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-ylbp9qdDj1E9Z8BVLOxq5DSGu+ajZNFc3ij95Z07CZFXdRELGyy7s2fx9ZxCyFAEZpRIaK8wmDczFwCMehODdA==","shasum":"9c1b1a8ac1b2a6e642d232b783c5143378bba072","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.11-milestone.tgz","fileCount":440,"unpackedSize":937134,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd8d43CRA9TVsSAnZWagAAJ4sP/3a6JNieYeM1fIEKLUml\nbQLlJQfpp856ZByMrHT3/je3RSzp3ELsZhFge5wiYlogD7whZ0IlviFnE0U3\nQVVt2U/VtKw4niaqiMuvfkpcNJePxaMwb9TliGyD/x81M+LSTza7STSSvj2A\nWbpdsmaMKMw9UNBENgU0DsB6KT2ad6fc3dm/HyhrX2XHjOvs8b1LmStjVCjN\nhU+p4ryWIvRCi0KBqk0BuoeGQL7M6QOfxpK/5bMgzOtiub5R5bzuHT1SxMOz\nJfiqzW/fFbgjY2t/1keLU1IuR1pMiHqCZd5NcrLsO/PIJTJ6gviqqe5DfITC\nI3bqO0GS9rMvWDE9RThu0Zr5h2JVNwJ6AevLPvk0jBNCDOoulDSrxD6nF1LP\nA5ti7CZdE1wDRme/vqFy5n6qIH/7LGA2zbG1ogZ6ZUctajNueWMKwJX4w3co\nyYjGsztk3nFfXaHXfMv8ND7TK6KUWQ5fmNbqnbBRil1iXLP9xVHw6IkrvdrP\npRIh8nwu2I74eyn/0SIyZteurGr9ngqt/l0kwQ0yWQt0oLVQTh/CfJn7XTw/\nsnmN/4NzKUmqdk81MHM+xWknYfUyAgmcfYIrf0ngQEprOfAM7E7JUCmQU0XE\nWhPUw1y03XLfwq0qgeyIVB4Gy1McGbXRLua7NnQDkwRiNZL712B5y5sx+Dgh\n1kKw\r\n=L1Ru\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFFnBvNQk1fj4aUgTp4uVd26UiSb4QM47iFu9a1PJcf7AiEAmSUarr57gYmvFWbDdStpl2HG4SPjcQRgTBog2mxuuKo="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"tb-web","email":"web@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.11-milestone_1576132150563_0.8404313625147386"},"_hasShrinkwrap":false},"0.12.73-alpha.12-assignment":{"name":"teambition-sdk","version":"0.12.73-alpha.12-assignment","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.12-assignment","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-3O/xk1EoP3wmhcJlDblxnBVCqez/Hohqv32Cz9y2XIuQVVfginb5zulA+4Bbn24WUAXTYsnZp4wt80YU3vfaDg==","shasum":"7e6d47aa0dce52ef220e477141aa63791a079438","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.12-assignment.tgz","fileCount":458,"unpackedSize":957382,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd8vjNCRA9TVsSAnZWagAASGcP/R5T+++agyYKoJhiSs05\n7+HFKuN7bwJ4uVAUq3Mnvp9w3W/W6yL0AeLV287QNF7VicRxxLuCWVrjUuK7\npGGRjuLlkG9RRKALDmq6VQ90OMxx3OLCd8JemQluqLzyqI00Ae11kHY3vEMk\ni8FdhkM+m3TPKorx9CmSzzOOMbyTJ9eWaMYPG7HFR7OFNz+4k9JBvcKgz/W/\nUkHpUQcQbzKGLlFpPYN7sbtNOJSPzIgSuFA3uQE86cHFCCJ55zTNqVDA0ckf\nIWggq0sJYRofdbz16LOqxZLKSLGspkGuS+btYwj54K6nbPzYknmkye60gSP/\nSMAdEgFaIg7Mkx8qeySHK7NAqlsV5tC8ajW43RvMGRaNg/mm35kbiTb6fe8P\n6VdrrF+M4JbBIZzqT3bVpsXZBkSDVTZGxdSDHhQX66U+ymlTMnL6urT73Q5f\nmmQAcCI6z5m+u5f4Q2RHVSCMN+Bjrg7AcfbuPawRcWyNu40iM2klNAm7DUtH\n1vhILTXPz5Tc2fiLF+G2PPLsJXV9ZZJ8dfhVCfe1GHCtjtpG2qhxoWn9AAVM\n5SgPI1bxliiptwWOApuiAkhgqUOkOXeT3R7/rou7jFYUm7KINAa9NScojlEW\nKh2ImhV1CGGpg+TpeJQPdkywv2wtoUtcSbXSAboL1davxbTZ9t5lKV/NjTHg\nJzRA\r\n=2BS8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBN4R+w6H8Q6tgU4Cwjvn84IkVhGV+igYKLSMcEjN/PEAiEAlLSym2gnmReLBFvhiO+iJgd8iyPpOVa545ur56UoO1I="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.12-assignment_1576204493104_0.4380734784027036"},"_hasShrinkwrap":false},"0.12.73-alpha.10-setHttpMethods":{"name":"teambition-sdk","version":"0.12.73-alpha.10-setHttpMethods","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.10-setHttpMethods","_nodeVersion":"10.16.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-nOqgg790hQcN1T3OE5iZLLtiLUfcCyhFWAUzmRpi4wngVwDtwzFvlLkEd186QYTfvtar/SWXKnAz1w0MrwUvkA==","shasum":"000d8345fadff65ec44264215acaaff5d8bc2b29","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.10-setHttpMethods.tgz","fileCount":440,"unpackedSize":938295,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd+EWFCRA9TVsSAnZWagAANWAQAIBBdkutd1MrgcJ2qiQq\ncMdqT73I3rwyWhMmB9WJu+k32u3YjD/VEo4ETAh6zlzqkBgX5vIqEY8n51JF\nRGvdK874I99cEJUIKVAEly6nV4qj1iERZZNmTT1xiiYaev0WWjmPgDvkP1AD\nP2XlBkg7zXZg1zj0hsDBGFi+8yPFPLrl85QG1eINGw2zIYcchpBRxmT36a0M\nJ9RWkkiJW52GCMzGlXE2OhDWomlwpJpZ8iD/Up8hcJzrvqmdmExaDZyMX4LX\njYcFNM1xaUy03hUlfuA0hjnnYqbApXJ6JpX5qsKNd7sW543Nqs4o5Sa7RCcK\nGvSglmR9IBTYQ997NMTlvtQmyPprzpkBhqMB9Zi/3rafeCbe56E2tEDn38l8\npL0ztVFoBKVHs7o9XwKom9sgDI1uRJOsFqFKeAryfAFhsyQ3Liq/eYkYNz5H\nPOWKC5FjokKT8MwxjV6dS9s4CsfW6xuPRlUx6GdXBvlZAcNAxmlzPVeXwCvL\nQqH6U0NaxB+4LOQa2fu8YS5csxEc3jlMtxhow8sL9lSlRdftAOdmqakznZlN\ncsqUNK96RrkAmg030xLOLd8Qa6EvLC9MFTkyB7CxAYjClj7rC+jrAGHEpZLd\nGJFQgR+jLWCHCtG27AJpvHHR3ZMErEWrHzg8Wjjiq9KqA4JyiPKMoahlmQb5\nbVb6\r\n=iV0H\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICdZ+IegNJz1Wef1PNT4PoO8411odCPNr/GuITzsDskiAiAaMl07KIUDGsl5olHvJP+0TigxSSh7d7VpY20EpcQXHw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.10-setHttpMethods_1576551813070_0.677808574230776"},"_hasShrinkwrap":false},"0.12.73-alpha.13-assignment":{"name":"teambition-sdk","version":"0.12.73-alpha.13-assignment","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.13-assignment","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-qFbfIdzoND/uvz+q3C/Hu0qg3bLNdMiZZEsO8RTKf6ChSfCpubbixBsz/xJ9R92SYqOr+vmlZOnuZ/nWowJo4A==","shasum":"3245d45d1e911dec47364dfc8f700799b9f6def5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.13-assignment.tgz","fileCount":458,"unpackedSize":958633,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd+E9bCRA9TVsSAnZWagAAqUgP/jd0fl5uMXO7e4jnGMHV\nBC1ErEnJo7UyBeNwcbp8VbaPaLIx5de9e+Wa1X0Ke4ZSK1WrRbB1RT9XVa1G\n/wfJCgAVLGt7+PXxbt3nJwDk1c8zoYs9kSCCihoSg8z+cv/6a3/SYpGYjV7o\nDzr4aYluHLh3VXfwdnjrAhZY6sFlN8UcW1r7rtZuzAy2ani7Vv1juCLQBAFs\nZuUD0LCjGudq836YoM/ZLxF4ZQmKQ6S6ESQRHkPHIZLYh97n+4ElCD5lihtw\nUmshvhkIYzp0MDo3A5TdzxT5UV3hSxhVtWB7GTdDnZgn3MD3EJ/XUiLLnTl4\nMG6qF+WmmOqx0XYKltbBGcpQHNc5xhzAIo8CNG2ocOtpxphhJMQjKNEyp/8W\nWpXD9P9ZDV0JNs3l9cZyGx8/xOAErJigkOJV1Hmqgy1V9Yhz5ErkWxbH5nOz\ndmKvUHcpprWM2gL5IOk1+JPPAIVOVCTj7/1R6QQVOOFzSk5QOytVZ8LGEjjX\nZAzsMGgrAXt+3plA+DZF4o4wXmH6mAy9aSOEbBFO6d+9Vjrw8vlnig48eAD6\n2tzRSkJ3Us+gxcNtajgGnwedjYyG2QV0mmWjVXgmZqfCUSCsXaiFN4ncIUuJ\nkLdYXpTpFsv9uhUr49WNO6E8tTA/C0E7CxFrWdsfbTE5JSgmGCdx5DPVmjZS\ncxJH\r\n=FgIc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDdYy8ordLST8iQeFLfqZzipJnrhUB3NPyFOEIbu2JkkQIgGWSrj8aX9/+gsBMsDFEbFT9Wvf+MlQN6bHLlnXrGwqQ="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.13-assignment_1576554330604_0.8805795717505449"},"_hasShrinkwrap":false},"0.12.73-alpha.14-milestone.and.lagtime":{"name":"teambition-sdk","version":"0.12.73-alpha.14-milestone.and.lagtime","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.14-milestone.and.lagtime","_nodeVersion":"10.16.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-uYaRM05e0bhK1Iw/EuIOaHHYf2mEzTigj2PSIy2aoJYmxK9m6I+AvuwSdQg1fN8zf+Eu+Ox1fjN17cFOmPcK+Q==","shasum":"2da2f049c41e6cfdedf0a572209e3447656ba825","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.14-milestone.and.lagtime.tgz","fileCount":440,"unpackedSize":937341,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd+LlqCRA9TVsSAnZWagAAx6UQAIpdQtN5yAnU3DcntM04\nxdephAl5RshLnVVDq6Coo1NpyAsQyD34UZayDI7zr9KXTexBhFfZ8sC/jIRk\n4UE3gYbe4XzujnFhwpBZvBZ6jkLO7MpD232EEGqCqiGJQdxMyJMosLsOmMp8\ntshMmaBGTaI4GdA59mrI+HDzqRFG2+5dnrbhBZ6iv1QNsoU6QGfABt9iHXxG\n5EYNkpPFSq2ayk+d8CVWgbRvZyUxTeVyMXd2aWEwLs63LH7a1ng8QCedlqPA\nI5HkKgEdVopvSiELJlPhGwUkVY9QJE672kqislnXt/vSADyxtGX+tZVi5TyW\nh31aY/q8kBA1XiddrTIFPXdja71WAtIpDtICcWcQn+SKk0bHfZvz8z/4iFFv\nMjKkMJpY5aS9FDrGN/R2aObBj2/XDfKF69X+Jf6rRAFxi0leH659+pnkICeK\nn/sK2QGFpFSAT6BcYXidfIfz57+Nvp9wIMjXHic1w7h8LuDwwe87paHx7vOI\nDsiy6B8AyLCzqFHWrOCjJGLBTME0CLzBHeniQUBTQhzLvVedSdWC0p1iaY//\nwdBEG8ecmO2jFAoLwSQgwDyoLuw3tjQyF/9iz5f4HJx6XgGZFkQpknDGDyF1\nZ8YF/nlYWzqYJ+Cue/fyoTJ+m0qOseSl1d7np9uChAbi2gIc8Nx867TZ2zxT\nlCJ9\r\n=ldxf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDDk0lR5hdMI9H2vMM0Wa3nYB05SzwiwZklgh3qUUtLLwIhALPXp9ha+VlmxfmcjU0IOh/JUzDTR3ykARbv+v2ARVcS"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"tb-web","email":"web@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.14-milestone.and.lagtime_1576581482312_0.3123425902658752"},"_hasShrinkwrap":false},"0.12.73-alpha.15-batch":{"name":"teambition-sdk","version":"0.12.73-alpha.15-batch","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.15-batch","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-f5yg0wK6viogWBvhBWuJCO8AkVLKxR36vTBaYPn2FlxKXSbDa+ThPoP7426h67XfZVue2KmAPsJYj2yH3zYziA==","shasum":"62c251c7f9cd6d6c2cac20532cff271aff5df672","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.15-batch.tgz","fileCount":443,"unpackedSize":955770,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd+eJLCRA9TVsSAnZWagAAQe4QAKTkeLY8MV/LHgSBoV5e\nSBkULjYeG0BRzSP2+vJ1PwD8zue/UCB7wAM8niHGlFCS2gohcezYFFaIirPJ\nu9oKJvC8bErm02iB2dvy+O2e/uCNV9R3I3mqlO+sSZfjU+ORkjEovfG4vvoa\nT5TWfEsrDywB0fhRnBa4yCFfvrN/aq2sNt0tRFnUnb9ZdNZ4w8fP8ySlvq0L\n5BvHctKPi8h4suDHlM2ePLN71NIfFny7IdNG6asF4TySasMyDO69espPD3OR\nns2oK7AG5UGYsR0iM1JvdBjavrfIEAmBD02XB81rGWl7iFSxCNmkaKNxUCbN\n80CaKpHGyoDJsZsZnHePdSjMI363NWmbdPTW6xyRan/ILAR2ciBu7Q4Caz7i\n619GS2Y9ILlr9xY2tN+6bpL+PIpz1c0jakaUai6kL+iGz4aLE8dB9lWMWDbK\nI5as3Hpa2IDBQKfwDgkwA/+z5KnaNemMzFzIb5Cs9P8va9Jq6YvQlAJwtDWA\nLx/pOMtad3XQBmnvnPrLR5iXobwdEJRJ/fxVTy39YuAEdWej6gknQ3CB9T4A\nkTTmSCO0yJhvUKqjNkD9fAHwllEh47GmNmK3nqYRxSk1RU0C0+4QOMdvfAY9\nDaY12GW69Vtk06bziRpdhG4cl5AxoGWdVZWutmgFSWno2D3LQU53XkmNG3Hd\npIWB\r\n=4OLE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCicoAte3hISp+zJ+AV5gerkDjqbpwXspv19Dkr3p5nIQIhALVO0OesEyq5kVriBOv2R7iN7gK9uWSPhfifkcxffrNW"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.15-batch_1576657483127_0.9713245989528851"},"_hasShrinkwrap":false},"0.12.73-alpha.16-analytics":{"name":"teambition-sdk","version":"0.12.73-alpha.16-analytics","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.16-analytics","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-Xpt7WMh0EbzL53fbIZ4JpZaWsFGTmEtKZCL/hfZATPtLAS/YJzwrTEbILoEs8V3+6aFnJr8kZZ4d0T29OtLUTw==","shasum":"fa7da2543eb8d6405c7ac632560676d2e510b854","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.16-analytics.tgz","fileCount":440,"unpackedSize":938297,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd/JUHCRA9TVsSAnZWagAAj7wP/0IPWZCh+I5sLLAik0q9\nubaLrLkPGeC4qLE4BBzoh0BtkzuW86/CI1aqQqZmpa+8HdinpPUPxkkQbQwI\ny8Ya3qz/9+csZge1UPslSCa9e5da6t4jASZS/qhwQ73QVblEKDknNswpbGzb\nQq/axtCvcEWEVpuHf7daJFAQ9DulnDWDwmE2iVLGtOoUqH83l7ft6aOQtktC\n4Xf7RnRDKFQWVnTaNfs+iM/8LccBVV78IIYaa9bxx2Ddo7fATfPhQZK7fpD3\nbnhht2AT5wC3q88jor9azkGcHNJ71a8KeMohksBLmpZo3h518KeT6vJU7G7C\nKgX8j2ajt9Ahw6JWtzkGNmV8ZYfUom5gwc+IkM9MObCKKDJ9KUC0RzfnWkzL\n7g04HemTKI2ECmzQXnGvdJzawa2/wvU4YUzqzZEj8AWXTPj+J7MHla6eUgQf\n8BkxBavOh2daHZKIUjRP+/1a8f36yL7O4qFdsi4cm55giwkuAOtHQKolgPCg\noBvYpLvOfP77Avzy3WbfStRNoW1N/h3CN4r7WQ0dc2Y9QD+avHZkt76ADYIX\nJlGT9oZdTeHDjanBtyULJPSZ7DCF3q0Ehhi1vFGszROqNI/xZaynW28RXucE\nD55MZNEybRgk4MbuIkIsNQnhNF5F/1Z1txRPYkGW4El9fVukI0WbGY0q28zL\nzmyQ\r\n=XPlZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID2MKMq7FnO+xUipMmJAwSb6+GtdhKa1e3AYDam2L/+8AiBRbW0+W06hL+YFwoPEUYuLeH11s86YEDF4TRm6viTrQw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.16-analytics_1576834310963_0.3448444359727336"},"_hasShrinkwrap":false},"0.12.73-alpha.16-assignment":{"name":"teambition-sdk","version":"0.12.73-alpha.16-assignment","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-alpha.16-assignment","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-KWjosoNd1r2fqB8ZL6lbTdsxeVUbb6LnPrFgus6M5gjsqsdm7k8YBKj4YCUouyuS2Jr/9ROvGxpVe+5ho4mI8A==","shasum":"5e0d7f4eeab658d35cde7b5d04ad3e6d6b7c5a89","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-alpha.16-assignment.tgz","fileCount":458,"unpackedSize":958669,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeAbhjCRA9TVsSAnZWagAAvtIP/jtD9iTPEdyF+PSWc9dk\nlgOj4DDrLUBJ1dhHHatLBvYQpEMEB/CPwZrUxxj2iRv0Kh2zKlg9796O07Xl\n8syenZalqg1A+/ORcv5s3u9wc7mx6gMCOkUAWg2BeC1zdiNfLRaJooWtapyb\nV3egu1SL/J4LFQDdwponIIrX0dk5KOkXbo3/kxnlv3xujk1WGKb0vLGUZGEi\n57YxPygqbzLFC+oEtgMMA43ZJVSl/JY7Ci7ZTxsp5GhcKrF41qACGsDpgUb3\nkPjLICoGPWIPnvKLKNMVXt39IOmUC0LM15u8yyE/HZF0xxCAihUwhyF0VI+v\n/2a9a/1au73Fb2ggofjA7tstJxH+kzWKhssKewZ9QEI/yp+THuREkdSLi3SP\nZ5svIq20QjwklcCD3rm8Setbr8IM6iNxU9y988m2xI/0FXQp9H6SGelDNi83\nekOBGy+ToDqXWega7VzXMVfVNFIi+ANHARPGq6IuazsZGimiHna87aEUaXcF\n01jKI+VcEkQSSVvJPOYEF8LnBF8swzCFlq85IkWimwsle9xoWfxnfslqBgXF\nvwdaoxZtgNWShvcHqjEB2DOP5R/c5PAdIOE3LitHl8Et44Hg76ENPYCirf1t\ncpooPTu6+2QE8YBlGbTzHy8bo10OOsRI5PB6t7xYj9i7x6vCGjcVPX7HdkWo\nByo8\r\n=8iGv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCuyxhauIXiPcm/egWkOw16O3VWdOfnD3JnNJJtEjGWhgIhAPg3dhpIjSYRi9Iq85Jb6ZMu68wB2wjI+Qt8/g8dllpE"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-alpha.16-assignment_1577171043418_0.316772032677475"},"_hasShrinkwrap":false},"0.12.73-beta.0":{"name":"teambition-sdk","version":"0.12.73-beta.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-beta.0","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-CKZqt6Nq0v8VIhIAySOBUJbhSjFMjtBqyQgsjQLubazJWLNDkI2ms7mZ7zRBJ/zP+hXf7qxdRYYjE/4l8tefEQ==","shasum":"08333442ef4405b68098b0ceb35aa7417eeb3ec0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-beta.0.tgz","fileCount":461,"unpackedSize":977456,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeAyV/CRA9TVsSAnZWagAAUv8P+QDbvUE9osyIhLdi9UCD\n5FG4XgfwOioyt76XJGthDU6rTFpFk0nAuhF/RkqJQo+/+cSlNXKsM6kOJLT0\nm8bigan40EWfK9sMVdmbyVyry/nmkgsnyrMWRRfeTsRPGb32JVxEUA3P6h4j\nSnDf1TLEQW8agUjFcb83D2kquGROGsjwBNhzIIa8RiwuLsgiMrGOPTdymdbc\nXshRnxb6HIGVkQrqNS0H2C3Q/X2mD1vzFTmpFu8WvCl5eh8/BRNxEx/GNHGW\nENI4q7aQExmBJ6Li/YtKw/TryaBbvtasFQP71PL5bWE8tAzbMXaJKKt6ZVVO\netqd0ZasPrBcWVeccBxPA4NlC3xiakM5/BN2TCSwZMTW+B6abY0xwGn73Zt0\nApp62YFp+4tSTtbjCrnV4aJGjpiPPlTTMTGvp0f0CvNPJx6zGeqY8wPs1sOl\nCeXGTtGYvXZurWMsGqXoFroOfOMXraSrvqJu2w90i9VSAiNV8qUv+FbpgLh1\nFXkChOF+m7sRJasGAozvq6/7w4W2TES+0jQW+64riMer3B0SYqYOtu1MAde/\n8cNro8OzRXF3JJMQGAIr7IEl//eeCZXjMTCiP8odylN8CjapvFK+6fmcDPJ5\nQFS0NCPEBA5vv4qdvfFEeDK5aL+PfFjwvONCEDLPEhqJQPwK2U/SOvdvACvN\nz8Oo\r\n=XMms\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE5mLEISbB57BcNTbSLfSIpLO0gEFe9o0DqroGF4A0SKAiBbt4Y4FP8hW+p8hrXYXJNuiRyQ9v1to/HJxlVU07VpGQ=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-beta.0_1577264510179_0.0038976092376485916"},"_hasShrinkwrap":false},"0.12.73-beta.1":{"name":"teambition-sdk","version":"0.12.73-beta.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-beta.1","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-LqW6aYm7pY+e1kKorP1DHnd9sKaIjKbspKlTgqP4MXSbCBtqbOUX6r1WQvO2uuGHbUuuRHCGzIm/frnay+pZKw==","shasum":"615f72d7f04d054a7045f285686a6101f3d877ac","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-beta.1.tgz","fileCount":461,"unpackedSize":978675,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeAz2kCRA9TVsSAnZWagAAIXAP/jRyM1TdANgNny8IwDhK\nqc6r7nxYQVUmCrWP447n9d6uefhtWIYJxG7vH3PzGmlmLU045+Gat89zBiRB\nVtk2CBaJq8oLr6s5PxZvKZUuks//ABrCEhx4HciJB1IZL5IyCRCu3NzWzpEO\n6HPy/tHtBYT1EjLp+O4eflotCa7AqMPkaqRsgkzzv+LNdeJdrUWm0OUMPc5d\nGBMh4xp9KvhNPNxcr6Y7RBEawOgMRWZtpdWy8WYPhVSK1A4BnDPw1T30dd7f\nTaPhwQpu/1nFr/WssoB3oGxLPHyEFn1pPvp2Kc+DKavooSyXmQx2YEKvUZyF\nlhOnATmvobj/VzIr3c/ChpL0iDbM/3EOk6UgHGGOpxIEA+U7ywjR+Y9j0pqS\nXPv8cOj55P5tdqMCnmwqDj932xeU9UbVD/tV9Y8ATPaEHxeyMH++lP/7ObT+\nD492r500YU1+CdJMJa63NU0vr0z20v9xM42nF+V4TxKFhNtBFsOxXhzTzsYz\nGLr1YyYl5Fyizw6aH3TjzztBvIaAZSsBhcgAhtHukgOS27pLpNNuMq0Kpwu8\nBGkp9JQ/bqdT/VXdPr+8Dmlxk4bHboK0WeVW+U1HXV344YvpX5MB0Z31pjKn\n1PcDOdlSWpUtELAEtlYk+Nnp1fsSxdLS9xakqIK9CzaoatRrS+RWGrk1uCc1\n6GhH\r\n=pHbF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFOSfRyZ7o2LGg5RVjYLe05ONSAl2Q4BVD4WJ/7HwNJiAiAWytPITAxgngRLP4wltUUo+Y1OKcq20CNpF/ILa0UP0g=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-beta.1_1577270691080_0.23326214302418924"},"_hasShrinkwrap":false},"0.12.73-beta.2-sethttpmethod":{"name":"teambition-sdk","version":"0.12.73-beta.2-sethttpmethod","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-beta.2-sethttpmethod","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-aZgwoKJgLzB7GF6wf0jUhh7Wb1WvjyEcUNnw/PmpxM9VDgMvNnII+sLW7M32hHuhfNIZ3cZSPaIJ1paIkGjSwQ==","shasum":"0988937ef54c4a2bb722384887c2256425b49fa1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-beta.2-sethttpmethod.tgz","fileCount":461,"unpackedSize":979798,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeA2RYCRA9TVsSAnZWagAAnwAP+wal072//xpElx5UGXjX\ncaoTEBSDRuAli5YfXGntyFA4PJOqjFjmkw9oEUq2jwZvd+x6mFE+iYPng+c2\nfkA/stDNDfvaiZOjEjU2iWziNk1Az8ywTZlht5vd297PO0AwirSC6PNGkXoO\niPP7cnZ4y+Pck/diszCCbR8IgtbZZkFQK2xSfj//jVkkJCt1VxI4xukv1iw7\n6JHb5uMLv3JAkyeGUmGFvrZN/K7d5o6/L1AajLXvwYzXunV2KTKK32q4aENJ\ngX0ZjbrYVx/yZUROiPs28yODf6OH/1wg2Du1vYxgTCSSAq/Za7NdpIB7Hnje\nmw7aFlFg9cw8hWTMk+MSJi9kJz0Cnl3YCr12ogoYd66Vq1phikq6Kxuf9tNA\nnQIdXVmpzu77LQ0h3TN1SH3zOyYhbU/YKRol60i3WpOGyhA79AyC3uLLWgBP\nJIAuBlCPcZpY2CLqHLGLVlM+8P8AvYFGjTQXgjox7MEfE4DS8XtrXQJb/Ufz\nS0WIEbLLeWODWBE7MWIO9HmFwYn/aGoMlnqR5AJIhg8CjVcan1gSKSZxB/8H\ntozz74uztVa8AxN1cF10TWG6JzfNbJNAGNXYA/g5HdSwZxFL4zWrsVgoRz3I\nUQSn8Myg8BaGnR2KHuqYTvz0CnHae3gwzlHgtRH4/fpLlFvqyuNXTksjXEKD\nPkI+\r\n=LRW0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDL0K3CSu8dpQhdn55rl5z8vGcw36o1G1o0kc2YtOMSsgIgboc0tkR9DQPvUqGnduW+dX0wGb6m71ACsWuhv12WIY8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-beta.2-sethttpmethod_1577280600487_0.19055806648806217"},"_hasShrinkwrap":false},"0.12.73-beta.2":{"name":"teambition-sdk","version":"0.12.73-beta.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.73-beta.2","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-gu1UIS5MZIPRv2SiOom33tiKkdVOznAkL2eonU0XuEND5Ve86WHd1+iGHUfa89gi9p52/XH1I7QkUH6AHnbQNA==","shasum":"0dd015c7d54ca291171de7a851118985782a1e8b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73-beta.2.tgz","fileCount":461,"unpackedSize":978731,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeBdzNCRA9TVsSAnZWagAAsN0P/3pct+sB6kOUBQkQrLuD\nxZvQG16+nf6gPwfnLm/w61UumVxSv/fvzfYHD5Z9Qdp+TRDkqVSzxG0UpUYX\nOnaL9IdVpYB5THlfnuo8FpRzRe7+4aorZthWwb0MBEAdQ6dHJmElQ5hJipmo\nokts7UrvKNP4FIL/tSrbxLa+ww9iaS2N9m31YM1Aul28qxpVGGMpk0K5Zjds\n3m2WPUJ0o/+KhG2E3PfmX6vVIHoVKdqmb45rrUrpjk0EHJONo7Pu0OmwOPhs\n5GRCnPAj72zsKATuuNHkSCCE8J3ZNQ5W8gqsxsMzrl0YBkTGUvKoKB4JmZkX\n/eqj4cU/RlXkHtzs/EnsHanjXJfXr17bvDo7vVZ3taTkusFhx2NogFBaeoAo\n1nSoG6VT46DRdif9DNZJGXDTZ+jAigAyTw67F/q/KLblfRtHhfSW2WB+bPPA\nBMIr/tPkDc1wCADMpeRl0IPkoWVbcf5Osyy7PncY3fozRv6UXtUgwL5FBD5j\nYJitvX+P6yjnitT48zSRnveFehor3a1vuD5B6JJ4Fi/I0CKPgGBZ9F4PrfVI\nGbXFkyRR9p2QxyF7VZd0/IaK76ISS3AMEzk2HgCpsILdGdaFaf+A69VhRW8u\nZeZlPS/UyAc4QOw1/35f8PIkhZGVNqP3GmL4aEgdb/We83XGjYp82yeXaNXf\n8iBV\r\n=2ukw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICAXjze0rlWMknN5nlbeBmd0VXMNRdYKw3P7kEl0E0p2AiAq2rUXmWzZcFAI1ScpQnMOW/4sB8jWS3QJLkhAWaCcyw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73-beta.2_1577442508580_0.8833143245479753"},"_hasShrinkwrap":false},"0.12.74-alpha.0-sethttpmethod":{"name":"teambition-sdk","version":"0.12.74-alpha.0-sethttpmethod","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.74-alpha.0-sethttpmethod","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-u6thJq+VxqpQ3MXf1/XKaKA3RukKx3Ml0hqT9xalgfOM0ybirkkDCP2UvDNUJzGscKwrRWhvYamh76ygAYEpgw==","shasum":"f68ae8aeeb3c667527f024cb1a8c5d47356d9f47","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.74-alpha.0-sethttpmethod.tgz","fileCount":461,"unpackedSize":980235,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeEY3ZCRA9TVsSAnZWagAANtUP/RM2ShP7c9QUdF1VJFSj\nE3wKAPuG+7jByVy8eowvMYg55gjtLT9KgPtyuPsscqYJpL28oqyd1XdMcqgO\n6rZvDbOEpCKayQs9R1TjIdHZAOZ7mr7O+7+30TqKlRAXJT/REZ9GRaGQMnfj\n+DmhN+CAk8kxWVS86CBqFUePpd/UXja2HCDezotgQeF1U8U8sCLyyxP+fUKE\nFcMV80KTsgiun15ft2eHLvzqVVdqsTEfrY/n7FEBCGXRLpTw5cKVPsVf17aa\nrgEhlGZwdllc5YRw+BHnXeI/fByMmZYn1bm8sp+YXCowSaGjqJU/ko717fNM\n3LXZgSfNvvC+iqzY9s1yIhkn5YUaEdOiFAG/ji1oLN0yUd0xDNfJnOxEe2p2\nrOHG2Zns5xFIDxSbLp9he2tcoGob8lxXGzLvyMgSQehw+1dpPsuzFJO3FfQR\nRNSErfctv51YGn8BulqAcTrmKtL8NI/YCBzSuapEOlv6ec1sNrVfNYJQwDJm\nrIcwfJsXKAggKv2OQWJwPaxbWGXL/EdFWM1cZ0ZfNWGJ8GVF2le3fiFeCMrG\n6+CgTh5qGutPEFaRJbf67NAzzrZYCUF0y969gtTpRhJlPctRZUPifwbw7okE\nro0MAARkRgjIu/Y8Nez+PeJ+hgKfRbRUY00AKC9sNDJtfoJVU0n19AjkYERJ\nobWD\r\n=XOvx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIATR/PwYwc4BuGdw6RISLwZaAHMZgrbwJk4baqr6AVvQAiAMDPA1f0gl5lRMSHh4KptXQgKbJnHc3eAUStqpyzDj7w=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.74-alpha.0-sethttpmethod_1578208728635_0.7647453860205464"},"_hasShrinkwrap":false},"0.12.74-alpha.1-milestone":{"name":"teambition-sdk","version":"0.12.74-alpha.1-milestone","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.74-alpha.1-milestone","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-+yYKcc9QbblIn3mxtEajgNYOG/vYJJOCQgpyBKRwu9goAdzEfdgXf0wdOsBoywvW8h+tA7srm3z5PM5UpOAXeg==","shasum":"7e1c6bb917f52639c4235ed5f583fc20cfa3cc8d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.74-alpha.1-milestone.tgz","fileCount":461,"unpackedSize":979851,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeEvRECRA9TVsSAnZWagAAKR0P/Rrlk5j4SwgmygBWIVn2\n7tY4IOibXXkbVu13QzXZy7lEy05xhqg4LzkGbQ5fyQ9ad1bAanOtISyV71h/\nIBzIUEXNYmwpe0goT4cTJiFfjCLj+80S8+yXhuvkazVjJFzvE3aFqk+l9hFn\nvcO3u7xEd/GxR+bBtZ65FOo9Tn/2yyV+kcHUruV+6C6qsdagRJBsYy69n05h\n0+6c5m9cb41IA0OBEkyUhV8DOD67+enukdCCjiFZsg5xYfSFvF3wfi3MGFYP\nONLcO6MUl6aJdje+kZ8nHrncWVVYV0kv/7RQtTOdRLVkwgV/DWUWxH690qU1\nzz4bilER1ljAlUAnm8zKYAk8SEQs8yPefv/ZOZZDyvVjp0VKqcQwwqBKeYhU\njOY2zRffbO5bN3YUbyUXJv78/Uft/iUFhg4EEgoA8uyFv4z7Bh/ZYQhGkk0r\nlj7G+rA7E384RA29NgoNDLyZc1G6UtuGrV1YFPzJG9hHFNBjPevsu06m+NdO\nxyUaU1VDajSN9QVdkOsAl7QMXbws1TVkusSlTe4+4THloX46+IDDhEut2HF3\nu5E1568jmNudwcLkSfveJIEP25f4lUYiSk8zK6fZXKAieq/tXxswOgnZl+sq\nN3Yhw91NDvJbJVAp1kAkbXOErY3DW5Az8uvPoTP80JqbRg6SVb+ezFF35Emv\n6+fL\r\n=yY5J\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCfbfbTswG0qo5mI/TbRGnTYyNHfqmUCSEYVsngG3P85QIhALhlAeFBsJ3ZRECaesEJeVdvWMhLcOZ21hoW1KIY+SPY"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.74-alpha.1-milestone_1578300483470_0.9599024200200816"},"_hasShrinkwrap":false},"0.12.74-alpha.2-milestone":{"name":"teambition-sdk","version":"0.12.74-alpha.2-milestone","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.74-alpha.2-milestone","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-oIwYT0/JtyIXKE3ohBtQWEH8MLqLTqSypuJTFd18yqgc5Gv8ld1+YdzIdjRe6rtWNihukKtBEWw68/IgMi4Vkg==","shasum":"6f6aa20bc74d03c8257bca04f14cc7eaa7b183ab","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.74-alpha.2-milestone.tgz","fileCount":461,"unpackedSize":980119,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeFAIiCRA9TVsSAnZWagAAIYMP/1v+r98HqS283hxxFxWS\nubbaqgloiYwH0Q3ORcvirCj/G/fIh3arDJjO5HyI4rz28EuTvIqUP6xSBxM3\ncdPnPtX0uWuwxM0sRoTz/tV9YeFVQOOHYad1pdo76q2QF8cl5vvz72oQ9ER7\nKXB1oJTjbzd4Q/MIpPZQbK98jZG4f7aRYjdR4VqgMhLhjDrJ+gcyPWCX+uhW\nwF3vjAiBJK7C/P5f4IEpJtfG1aFe9dw/4e1CixGA1JnDuTFULsjNxa8g5gRN\nXtpvJA0+Xfj7C3mcHaTjRJe/79uZUE23skdLYlaoSNSUnFAXaGq01g81VtdJ\nbGUrfxgP9T8NuppnIELKc7sj68Uhspbaki2dav+XM8r9hcHRcZKi3f8hvtCZ\nDHHwZ9x7NqlR7Cwk/Ft/ujVtXJrdbGb5SCOmwgBsdYq+xR3vuMnRT8z7KPdS\nbYGHhsa/V+1gzAXvqpVcbKkZXqUiXEe2qZOYzzWdiM4jT1ln2CU4ecoJ0AXV\nv/ftH82FMQsEynx1UXbX+ZNyarUfWsN1eMxZapqqeVrwqi0AR2t18JbskvQF\nxQ1hIYPSBYK5zgCshwM8dCMnEEYSHM6zmUq+U1odVljwaBvBDMhJuIJPq8tF\ny74ZJLEwc1znhxo977cS9qJuGInS9A65DYRBMYfa6mzvnwXmEi3ZZ/R63t/A\nJ0Wh\r\n=ixYk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHzTBJkUhWbTSztWpI4jEyO+SAT5XyhCLvqqjikYxNPgAiEApReLQgLBBSVdJbyZoZAZGs6OB/ZWt2sxu78KPVJ+AJI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.74-alpha.2-milestone_1578369570169_0.40418424922741236"},"_hasShrinkwrap":false},"0.12.73":{"name":"teambition-sdk","version":"0.12.73","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.73","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-HSnQSrkA3sCKb5A1rnirDrAU5diYcgOdxIr4QRb510rOkUkGX2cXMyIzoe7Qyo2XTG/B3oh0ENH+508xYNgGtw==","shasum":"a087cb7913a1d0799e30b0dd86d0bbeb9903e047","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.73.tgz","fileCount":461,"unpackedSize":980078,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeH7TNCRA9TVsSAnZWagAAtc8P/RPczX0sVamPLuKuU/wZ\nFJ0G9ejr8sfdGM4QMkfmVLKNYIJ+SpWgHiD22sG4bibddOqr2MU61bj5vpxW\nahLlzMj7Ns0RFtyywFu1IXGtiAgSZfPxAApHD4HiuCulJg1SvtDs7RtdRnIM\n3bKJu6yk2bifNNFKdFzma+Ai4vqme/B5M7ub5U2qaoCFC2nQrIVpikvQy2dc\nm+Hb2tq6dzwNwhYsGWPrlmAhqWCZykAKNxZqgYv9hIOGdcrwNo3H1uW4OVD3\nzGaGHIBQil/HB0eyRJtzYgkrNtYRHOFXRffVSSIIH3FqHlpp3uPc30XMhcGm\nc34+vRzqeol74/iKDQAKyNGOKH81eQsEVA6xt8Sh/BLr7pKoKQnhfF2xMwKU\n79WuQi0Z4jiBv97Bq0N+rO3BYY9M/ohFTM8ujThfzWBOho+9jRB/DATWFrUR\nxtDYs3QjJ+5Pu3QHjpmNR2IIjqoPkpfXgTwflFC32Twr5cGS2kbUt1Mrkaq8\n1o2JiCliOfNTOIJS6ynsr28i/hXOgmdiTSvyimsAHd0cGfGxAQGZj1r1GTPL\nCwqMhgkskIlgpa0FLwQQesGMhk82dOPnSpNVDQhCuStTdohc1MrQSbvoBG6L\nY0mXro5k/1Ucog64QH1JyTQicXttj3nuXjaTqKanPj48STOiEk9JQNO40cHD\nd/I/\r\n=0ymt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE+Mb6V5cVABgwlX/XfLtnHyW2aXL1tHdLxsk+LuEQ35AiEAsOthG0hI5p+SajCL9a0LDXpPqI8NAw0T4iQn8uH5eQk="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.73_1579136204411_0.8066169714424292"},"_hasShrinkwrap":false},"0.12.74":{"name":"teambition-sdk","version":"0.12.74","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.74","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-o0Yz0YaZvK+SiuLjytFpv+zzu/Xb00fDvQKIAoHL9vZ46zacIE+fk8g0Fxy/xRln6t8BHlmqg1CyaWAFaMHKlw==","shasum":"d5773299d86a99328a784b90f45292713352d893","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.74.tgz","fileCount":461,"unpackedSize":980567,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeH7bECRA9TVsSAnZWagAAUxYQAJFBI0iNqJ2Ks5AzQZRA\nN8cSsHqsk838nBRYEMNR42S6ektYfBScYcKsYD22yVSK0iU1s5XZyhoysfaq\nHz51Fdex/7ahe0V9M47L2bXChuoYj8rvBbpCSdD0etXjUpEwvI68hOADvcxm\nh7WiuZOZNOJir0HoRLpVXak8glA0tGcEmw1jyxP0BPmzyaueUdEWpCAVthU8\nu3qtlPrQSWYH9/IDSKkuWgq9AsOV4CBHAR7G7qDsabXta5W4pb5Nxt/tG3ni\n7bFIaI2JpO+6qRpNUBxGCll7wAmDWCtiZ9SEyEe/CngSAIJlGDntWIBtlRuj\nBHHBmRESpoHvAdRFU3EJzDSm/D6M0wh9gj6npQK8ird05wQ60dMyDGtps/Gh\npYIfcz6jWt/iAVCzqBoTm35G2vIx5OudBBXHAls0YQ0r64AWrtaepoOiZf+6\nc0mnhUghUXYYXJk08T6yBXpGMIIlC8O+2NP1Cqlg3ePMQYAjG++6xBLd3SV4\nblD3RVUBS7x/nYHPPObg964HkCOnCBgr15oww5TqRuRMoJrEyZev02YA/Slg\nFNNCy1Dg+irvoxGrw5JNeCkVLYyfG5kWyrJupEI3zbZVRlANUbQUH/KxOZlF\nhoSZTNV8rRnq2Tvzxiql6C0prHVXjj2IfyOntEPFJjnT0KgRZtRrbTS9Sa8B\nFOQp\r\n=Tgf2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFvvuzhBbFxZyOdolZ0HkHGQ3VgqPK+id72X+KWKkdl+AiEAn2WwUkNVBkuPHUbEnIvC6NddZMBEY5gV1r288x5osmw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.74_1579136707939_0.24779143140240678"},"_hasShrinkwrap":false},"0.12.74-alpha.3-approval":{"name":"teambition-sdk","version":"0.12.74-alpha.3-approval","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.74-alpha.3-approval","_nodeVersion":"10.16.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-V5tYEzdYauspHwYf3Odtd+7JG8xXTWQvYsY2V6785GRwZgGfwEx41qNMoCIEFjWYsRM/5fj3g5W+9YJNVmwDmA==","shasum":"caec3960eb69c2be0ec80e3f9887e031e0ed6683","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.74-alpha.3-approval.tgz","fileCount":461,"unpackedSize":981864,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeJCOxCRA9TVsSAnZWagAAbKcP/11zPmTCmj1wT/KxbB0U\ntlcx03Ce0iL18wkM+e8XKvPIMMCuQgvH0HzgF+xxYdY+6wWatAYeUOlMrWc8\n8JJ9IvLq1m+X+r/yZHOaTvIoc0LHj5V+9xFUkgboMuRdQNPPtTfVCPFs6a3V\nuklpxODZv6nTL7QstCqLC+3ZMXGcDcJMZ5OySYZXcD1oP2nXwaAcLTFdaini\nZBrMPV+YTqHG8KW5M5OrKUA4J01UOmH6wcleLbWNCttXApPAIWbOSQZxn0fC\nzjEM2tAofBD/QeejJ5cVxBdxyGbHs8FTM7XS4qsRX9pQVcQmNe1I5iURZNva\nBKTCO/j5+MWpdFdIyykSXMrG6oHXblDV+W69Cb8QacP+dCtr3KoOiHJ1RsXK\nG/oG9Qn7hdDJYNsQfikWKzS7XgEYQ4tLFgh/kPQj2CRp8UgEDV7gDvxT6DdJ\nxVJQJiWGTYP8uhwaUZzUO9NoBtAdtMmWJ5ZPyEBqwnIQoqBneT7k8cbQ74cs\nUYJBvMwJx3WXPCRg7h/qDrnfojL0fAxGnzuBd25Aje8kSV3jDWF0Y4okwz68\n0zjWWb1GE4fPeUzNS5K11Hy2ImwtLj5KMWJW2VyzK+ajmw8Db3bqlZ8K53dL\ne3c5J6syFjvdLpAplEKfMU/CnuJGIMT6T/XkVioSXnR/jCDzVEc1dJ86GMQy\n97S5\r\n=l9Ww\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD8pULlsaO7papVyVDhXdTzTY/aYxvWaaBAT86nSI9wggIhANOyRUXVJl1AjBMIIPF4y88woY5Y6tPoXgXlKHZbzgNb"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"irinakk","email":"irinakk@hotmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.74-alpha.3-approval_1579426736831_0.6527908300479435"},"_hasShrinkwrap":false},"0.12.75-alpha.0-sprint":{"name":"teambition-sdk","version":"0.12.75-alpha.0-sprint","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.75-alpha.0-sprint","_nodeVersion":"10.16.0","_npmVersion":"6.13.0","dist":{"integrity":"sha512-qU4joyz/p9Ky481l5streErc0WtW1lgR1okgL4Go3RqAthvW/e0KdNLqQh68hxNxFcseJQYC9tfqtjQd1UFBrw==","shasum":"b5085b3d68fbebd17e0b83a16ce8faddfdbe32b3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.75-alpha.0-sprint.tgz","fileCount":461,"unpackedSize":981024,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeJkdUCRA9TVsSAnZWagAAl+8P+wYCaVmvizNphSmQBEm4\na5b5qh2KyfDF69uk/CLVvYcgFDpV44Xf6az55SO6x3QVS1rV83JauI2pviBL\nkXfe0DE2LVmFBEKI9xdNyeMprhOXJPdYxo147X7r0oHZgVEx2HaksgCqX6BC\nYSBH5csOKW00NneCo95EVkzD/bCFJvtIdkG+4ILbqKYJaQzkYz4Tmm9AEtxE\nM4ObWVwotLdEC53WcHF6o44Q1DJKfJpx3frhIBPcok6oLz1mZaQVTc3111Fo\ndZ0Kc5k9LCWPWiI7LSsXeRF3lLB9JsTJCfYMMfC78eZfHfR3LHaM1tCKHlrh\nw3aUSs9W8e7HjSmt0DQWLvxSi5OYi3+91YPMkyIn3GrFrbsQf9RZsmW+t0uL\nHjRa4maAnmYs5i1QKs/KJ3hT0G/DUHdRFqX7zJMQ68vdR61SANnRY/FvHnpH\nEPm1Bo969LPvKXszt9FHExpvhzPSdhDiJPO1TOHikuMJmWt54OZGBlQaboUO\nlZFxHCWlf0Gi4KbLnoiYuEzmO6inF2nYVHUGQ3/ZT7W9s6uT6gbu4sZfukXM\nrdQypgWURF4nT8NIjZvU271cGBljacOxjl+ZmieS3TBiLX72UYPCTD2D+Q/J\n7WUr+pelYYYRcfK7sTxJQPEi4homXB4goNwN0o1YiAs9r6zVSg/D6pnYH7dr\n7RbE\r\n=hAk2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCRLT7K5XNezMRPbXPqq2nf1fxIbsoeVelF/VoSY/XwFgIgeYk+LPajqPclKss8BYfKUq33P3+rWKDCtao9EJotJ58="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.75-alpha.0-sprint_1579566931195_0.8632195670991989"},"_hasShrinkwrap":false},"0.12.75-alpha.1-sprint":{"name":"teambition-sdk","version":"0.12.75-alpha.1-sprint","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.75-alpha.1-sprint","_nodeVersion":"10.16.0","_npmVersion":"6.13.6","dist":{"integrity":"sha512-kSdZbFwv6U7p19n361LnDKZOaaDEt4EaXMxyRUytjOBWTtUxotDWhnD/Hvd+yP/ofoubZUFc07xbByVLQrBXOw==","shasum":"cf030b02b0c7145f5c6d4c239e70fbf72b4a3013","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.75-alpha.1-sprint.tgz","fileCount":461,"unpackedSize":981247,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeJ9CxCRA9TVsSAnZWagAA2l0P/iUjpjiYIRSluzaDyGCB\nltu3eWYr8cS1ieiS3BPBrnOndkCT7aLFW1hVLeUpyCwbnGmpwK8Q7erXNmDY\nTUkdoyrndjUIEd6WGDVBmUxJYwoPvLtJD7ECATQTIrBkIyiobOZ97UoDE49I\n1XUNTmWCHYBv82fVXYIjPHg8lYHgIVI26+hbY/aX1/wEgAJE7mZ9zgmW6le2\n7o6hIb9wfZLxBlp2h0NOApHNJhG0QoeRqEM/iYgmaahJGRXr57/pUuX3Vpz1\nfqNre20iMl+efZaRWd/FrQOPyI1dlrZF6hqI14YKNQ68VbNrZeJlhpAmYz4B\n5WpLHvXtL+8yMCmHUN1KBHf8p+/NAtZVWp8nm0Epa1LX7U8IWrwAxOyvaTHc\nRGyMAKeMOIVRozaaIHnBjRpvhsG0IxKKJSzo58BJcrFVk0NyWfA2Dl9TdeEl\ncxRrZwUiK482xmf+X/hZL7DS+ZIHQSmNvVZEfVcet6ji1SFFwDkUpCYcy/rI\np03WQx+8AYnyEsAQ42NK1AYY8mH++sddOOqCYm82MA6Je2In2Bt21IzJUfxh\nmTvFmAuYqOHAbpDNWIUQv5L1v3cuZ5LPUDvcvTxFnIdVcKdb/f269h1esVtT\nFyw8RHP3m0Lj+PXu/LEcqMBzQMjB/TYbOlFB1zIIWP1AbV0MVa8kFTWBaJUW\n9+n2\r\n=5A/O\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICY1kQY+gry4LqE3As+aPArVhc/1hZwujaP8ieJY0yN3AiEAwYN6ewNQySeQ64DT1yKc2sO/fYiHxrU2NjWrBJKgwdA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.75-alpha.1-sprint_1579667632834_0.13811164363437767"},"_hasShrinkwrap":false},"0.12.75-alpha.2-approval":{"name":"teambition-sdk","version":"0.12.75-alpha.2-approval","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.75-alpha.2-approval","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-821ruSTxib/ZA1FLNqzk1dzjuT+J0oe9qgDWpjJV7LE6DoEPs4v4Nr1+H/nZSvrGLkEJ/Y6yKK9MLUbg7CSNzQ==","shasum":"1cae024d02449c5956108de25d9d703db74b3d32","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.75-alpha.2-approval.tgz","fileCount":461,"unpackedSize":981736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeNRk0CRA9TVsSAnZWagAA+EQP/RyHiUn+xZ0MQAQWIRDW\nleDRSRjBnJoouPSJp3MEL/O1kJhc0ZxKR30T+4egz+aYf5D3o38mqhr5vtjt\nXYtUwK9FFCF61dJDNl6DeW72Nb0+AE5PJc9/Kt+7ClXX8r2e0OPjs/o2qHiL\nIkuSVQh2/MUrkiQMy/ccCSTFU7ALtb1vIseszcvcHSbLS2j0P1XdmylpTOwI\ncul07aA8oKLQLJHLVglmODRkpXRmVNcgh7XZp2nzqE+elHoZ8H4JCfBOblDN\nECO1X9UmRPN6nQjTProSOoh1BZ55uD0gW/2673p8W8LH6vLE1e+rdlg1KK+M\nJDkXIDkkzN64JCSqNS8MgUVCUdC4cUjFfXnhjjZPwHKnVBkEZQ69n+cU5Zo5\nW7CfO7r+UIVCfzQA41xPs7hZgoHxDPaP8Pdmh4IKvwLgDw7enEiEMM6L8WkZ\nYT8Owu+YAkmECXFLfTh/w5fVv75OkOMO90cJ1XEMml/WJfQhPTX6C0T4PKZ2\nv7oCgHvLElCxp9whsXW+yDRzkQtQ1IDBGD6fuZWpPERwUFYkPbLMeuoqHmpW\nzu7+eunWcPsDQzbEaKqvYVciEfrtImbRm/NHembU6PNIrgt42TmnRZeBRUyA\nbk4ZYVrKBfe9kpv4BN0tuYYCWPz/AVv32vhjzlYVOyjErIV0ZgeAZxYN8nrN\nC5bs\r\n=N6PJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFoY48z87NVCbdHDIQwMnG5FIYAHeA3ddb1+XczyOjx5AiEA+oKnuTAd8ojx4vkJ7dbSVal4zhAHcOHaM0/SHW3n/Qw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.75-alpha.2-approval_1580538164095_0.4037946058676063"},"_hasShrinkwrap":false},"0.12.75-alpha.3-approval":{"name":"teambition-sdk","version":"0.12.75-alpha.3-approval","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.75-alpha.3-approval","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-tp9WhL1MbbQA2LMb4PdlkJtW2sr0mtHHvfBSrC7hqyfpOHNyPsa47VfuWBWfOZhmNNhs7eRvSuhUSq6lhxZL/w==","shasum":"e0560c3ca8e0d0870d120f132e017b74d384556b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.75-alpha.3-approval.tgz","fileCount":461,"unpackedSize":981537,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeN8PiCRA9TVsSAnZWagAAX+gP/13e0GObuMJJcBJeX2Eu\naBD8NIBiW6e4pTZsIsZMmmbj0DoPq1tDhFIj+LKAfM66Y2lGv7+lpJ3CZYqu\na0QcPK7ZVe676mQjImLdjsLYiqMvWCjecavtfA1RJmn3AcmB5657uMJpev5/\nsHvbBqNdu2McHZb5SQT74dmBGEnMaTpwgN9C+FYfCsakhvXKlTkmwy/3PPyK\nBIf64zeP3cPH2vH8bNRxxQd3H/j7p6p96dgB2NHT+AO5L5rSxK7UlgY+I7rO\nx54S4uC24PZUUUUoKThRN8h3+KeaKrgnCUvD6cev/bLkZe8oxvoC2gfYLo3L\n4s+GGOeDpV3qZ5rxJ8/KukSyekLX8CPnp/ZYD7MIBFxlD6ZZA9Bn4CTYCoGx\nLiU6abb3ST8ADx3/ZJQN1XsHKEV2cHI/kNCYlnzAKihmuUI+ebSXrcjQZHZ8\nn3McMM6hTI8cFtkV8/rbSMutngka/GPalr3Tq4mg3N8sgZVNJCbt5mwBsq2a\nOhBcQDZHUbqnSJ1CXI6RUBLU5cm+pGrTW3OE0Amet6HfCdMevCdsT+xGLe7z\nwp02pn9HYP2U8osd+QKw+GZO9qg/vKkOcw/QYT6yuqFDxBXnnQNIxwElgIPf\n/z9K42buvaMbSabUyZtZ7G3IEcjkP/oWyTFwxIVgw3t1pSv2AcVy/GQwmRuc\nXSOg\r\n=13bw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE1gzG/neDoh3XDLaGEqyx6LTaxKX/xnd+NBtK+aAU46AiBz0/Gi0dal06SAXehuBWEA59p/ONG4wWx+qSvvaaKuXw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.75-alpha.3-approval_1580712929568_0.001126943461837504"},"_hasShrinkwrap":false},"0.12.75-alpha.4-taskpos":{"name":"teambition-sdk","version":"0.12.75-alpha.4-taskpos","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.75-alpha.4-taskpos","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-W8tavsmrNR0RsC7rFyZeosRa+nKoqGkF4cs/+m/3y3jqsOPm+UsakYGw0x94XgI8KiXntnh1ByvqkHD5aXms7w==","shasum":"b08c6f5ddd6de6a87f2ac8426f0650cee9411d93","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.75-alpha.4-taskpos.tgz","fileCount":464,"unpackedSize":983165,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeONEbCRA9TVsSAnZWagAAEEsP/2kSc5krCC+WOwPdzPlp\n0sv/rgkdCDrtig6kQWwC14U3tcF4fqBRSMcCm/ls9AueIqtJjWhyVygECNOj\nbeZKmJ6hiF1MIeDc9DMkuCMCYp0O7fReSlbDrfwoceWxl8JafLn/mzVQKNKl\nv3CbBp9IwYmOsElRWQZi9vvWmMM9QfqbGa3tK85zBWhtl3Mud35EtXNn/mLb\nP1RRjMioulVB/Iwerfr9OexCYme4TPucXs5pkp8Pvb3qukKtQkwZUA0NIKLn\nwMNoMvh3DWaxdMCc3/FbKHObqZxMZIGAo8paUkfgiYkK8tvxZ9Tcb/QnnSGZ\n4ULQgh7gKIS/NrPcIWRnoAWor03AXO89h32uUvM1Ndijr1VAtFum8aE5c/do\nMJ09KoIaL3e6RVvRPZAJV0nL0NrUSlPASaX0UVkVXysBUI02eM3PSg4sCdD2\nhhzyR2NyB95Unao4+LIwKXTujgw9ZzUbZc1y4V5NvZdESEiVIFi5wxYnW0On\nHtxMRwYN5TteMq+8gr3t+J2DcBrczX6IeGn++k2VIRBRwFPHAqMOiMb+mpAx\n24aDY5YE3Ipj6JRB/Wf0WEoyu5xaboYUYoVSLseLyT7VyE97OzPhxm8gnwSr\nQHgGCjQfAiTwszjhbak3Db/5X1dbPUUJvNYNOVP95ANau/OO4RFIhdQZPJmc\nbrw8\r\n=RuZa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCAo4nyd9zX+q4WqNDDgWxeWIabKv3MqqHPk8fALYGUfwIhAIJoGEKxzfrlByWGGieXRZxwpxqeabMt+JNduKEOtkt2"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.75-alpha.4-taskpos_1580781850724_0.19581382029768046"},"_hasShrinkwrap":false},"0.12.75-alpha.5-taskpos":{"name":"teambition-sdk","version":"0.12.75-alpha.5-taskpos","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.75-alpha.5-taskpos","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-D0lWLp96PO9KIjYOdKqJfsssKeG8jhHcJd9nllPhd9VCvEcGr8nq5o1hzwlLKmD6K5240HQ5qrRKZWHDKoGFOQ==","shasum":"e540bc093b599d256745818c040f4fdda4849854","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.75-alpha.5-taskpos.tgz","fileCount":464,"unpackedSize":983457,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJePRdFCRA9TVsSAnZWagAApPAP/jFwtUpBtZHpHyWdP6mx\ngzt2C0iwCbP0pWteJ2z4HmqfVlt+A+KbJHBndpO4m2YDrclnbobVHQiqynE+\n73g9o1UVoea0Q7yHT6wxnSflD4yOwqrFuKgExeUVytiQjdN4cLbNhD+yAVk1\nlpCWjdcu2vN6WftQtLqemoQovBPgEyUyo4Jeza6RmGk9r97hqjZi1+iiEw9z\nSseSXxwInf+Xp8G+Wy7ZW/0iBz6onNqlAn7S2Jhrb7t3eNeKt2ZXe+gL4kdM\nqJdpCIIvyG+XB4wI5IuVdhbeW3+3HiHcxQWsqaylhaKN+FXFFBEkXxnrJD3O\n3koAXGm5dMhlN6aVvUNXHfPTY6O5+3Jf0qa67QKoUtVRkJxIgU6kl6KLqr2w\nWIzdLjrH7ydn/HLdf2TT7aHUrWAgrBLXlvXr4N+8l6P7Xs6A44VmfEs05DDK\nm/x2VI3yw2fJjUwywbbvXlNNwzfLnrunp9Qq28dojrP6NAuUlbG63+LOwVCW\njOqdZz4rYKmi+P3tLfMWtRGzkUVJGjo7SBc+yujQpS2GdgdcXUsBQPj/5Vqe\nMib1IpAUcTPnXGXPuSPSr3IDBppeHHi9YfO7U2csgfXkl1Qbg4mW+snBfXal\nBBVwzeqEue1oPgbYn4QqVrn7o1eih3Lm9gR1DU2wEIq05PJj+JLrwSWlyplL\ny4px\r\n=vSTJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBuQlfFD9nt36SoFr/Nj5sYpz4OnLpium2xNNfE6ZWXNAiEA3V5KxRl7lGFTMckgGEVKf7VcgaKFyCFeVBjMvFn9b8M="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.75-alpha.5-taskpos_1581061956619_0.07759984359477179"},"_hasShrinkwrap":false},"0.12.75-beta.0":{"name":"teambition-sdk","version":"0.12.75-beta.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.75-beta.0","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-OFfRdUdyONE80oTHAucXmFx2UhczkAwtwDJDJmZxIDctDYiDMajdlgwCvmWQukjaUG9rV69UOqcu9yRg8JNL2A==","shasum":"2df021cce894b90dcf4f79775ba1c43dea01c54e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.75-beta.0.tgz","fileCount":461,"unpackedSize":982206,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeQ7U0CRA9TVsSAnZWagAARhcP/1ooG5BUdVVmhTWXZPHE\ncDrlM/7h3m6tT3f0MpghUsBont7QLQdGgfJgQ+8aL+yg+j/chIXeNQbmweoT\n796ixFd9BItpBP0KVygB3pBe3hZ/3XHqN8T+Mo3PS+yo+3V8ILpZSlX6Wgzh\n62SpNCj/6CVhI5/Rz7n4aRHTzqxc0tIBFTMtXadxDWnGsQpsBbwPSenAllSA\n3KY7XyWt1yH5jwn/sB6g4xOWOxx39nlsDVdUBKPlJkVIyyPKr1ZqETQfQubj\ndJ0KgWLqmjY9/5LqCMFKgypJOT1VogUZBCaokzPGPonJ6qirJTQcWlPUyJkj\nle6By6330+9AlyfkGnH0+96f47h1/hECLMHkDMsLR/pdeAi0uq4eQfFkgYz8\nEOHqnWY0pE7ObGFcaNYJMWg35vHrecKP47/+Fd29kyLDkbj091/ZfBoHucMM\nDmJyUebRDcVkwWmQqqFOIgAiTq3s6GfX/KVIHExPvTlzfIGqEICvpeyW+A2U\n3pCrHB2lzJFzydOjWjxkJUM7UT+KaeHqP/usawDJCWZPh2GWRtwabpI/OZRN\nHYJi8bos+Pij9mkP3MyoVjJh5DWM16T3CajgRQ1q2cvBk/wG68iOhthSwByY\n/G8vBh8W7ERZwXacc6t4u8to6e1B3UxEQ//1Evo5PHNKR0NHAafm8uBh9StE\ncFN8\r\n=R9Qx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDjbe9Va4vMev13cQMB0wsY7gRzefEI1+9ubcD1r7pLwgIgJEKnKwtTN3X/aj+kTck5bN0vwRzedpkoz9ONJ7E8+UI="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.75-beta.0_1581495603434_0.3258186852541931"},"_hasShrinkwrap":false},"0.12.75-beta.1-taskpos":{"name":"teambition-sdk","version":"0.12.75-beta.1-taskpos","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.75-beta.1-taskpos","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-M0HFpGDnn1HrFw+9h0VFYaBDpXJXneMvyjLcysqTy/EodD1zK52wumPAlMVep+x1j7LJslMlK4Fi7ERg9C5UTQ==","shasum":"60bb0123e545cec2759794a8d6928ef0f38f1cff","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.75-beta.1-taskpos.tgz","fileCount":464,"unpackedSize":985088,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeQ7YhCRA9TVsSAnZWagAAfiMP/jzeXZrq2rAbEk6Ednbe\nMtzARSfaHlwpzJBzYItjkGsTw3LJ+wjW2uFGwflHremzl3IRngjzIQIozks1\nV4js8ZL4xpJcdEfdmt7hdYyp2P/Ho4leRIJiM5JFkwz2T+bUhEiRyd+IplS9\nnP4eFWNnFt6nLpcBmEX2zx9nsiwXSGO/50AZ3GluBpP6UT2kQA4fkvkPDQwi\nHIiRaKAjFMM2eTU/D+o+E2qgSH/LIHvbU+4SW/qmXJ7ESK8S/ZjeJ6G8VxuY\nKAsObLflx8lPM5pNjP3EwAaT/sMAHwoXkow6wvQsoju1+F//WFJK3L8iFPKr\n7PtrPHBMF4iLczC4MbXYrAqQtxay+537r8qtYTbzkxhinI0wQZlByK2je8e3\nZsiEJgsiNsObmhAkcYU3X58yNerj31dYOtuDfsIQ5D6OMw3eL6pcsgEAWexd\nVUZCweY3iABjpKy/CErhq/MZGscDlLmmU0cHXMrQ5+EOXSYWf21qxX4FqmX4\nBq5C4DPLsGR4I0Lj4xUnQF8BXeOV4KKT2Psvu+wx9DdT2zb57NtZAFWS5bAF\nTybKMuDQIQtvPg3WWq4ZwD9LVeU5pdxmALYItIRMZlCEzi3lsNnKIbv14nvf\n88tGHUUGsThrvicKj1TwXtcQP56OUc9P7Ra8VLpQZlmi2CKTxVPwYwyXCqL6\ncH44\r\n=cUOh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA3+LwGvKLBat77m++sN9F3vLtZyanw4WZ4hI0vInG3mAiAiA4UWdK5Ps2W32DZ9bDJkrC6Wai38Yr8D4/kGWn7tGg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.75-beta.1-taskpos_1581495840993_0.6680062305673393"},"_hasShrinkwrap":false},"0.12.75":{"name":"teambition-sdk","version":"0.12.75","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.75","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-3fiABQvN8tQ4nIIhYapjQPJ8PdEkOTBhscDuGdb6JDTLHn/VdIXRmOvpCWz0k3FwNo6fATQI3yCVQGmLch9QwQ==","shasum":"02e20082288cfc5248407a21db0aecd5ccb18461","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.75.tgz","fileCount":461,"unpackedSize":982060,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeUzG6CRA9TVsSAnZWagAALo8P/j761mhJgvsgwp4vXKKK\nIRfm/N0FoakN7PrYWdZ5OnhBmfYFNuReuExvVlRGyHVmZifly2EFWoDWc3Gj\nQyxQjhYw11Tle43gv2VNacZjVlE1GPrdRG4bkaFbn58woILM40Ab3NlUq8sr\noqxMQfySrHxYaGTdQTudXbc+NOdyKjmT+c2rO3k18TwtkkSPEP2zyBDRUccN\nIRyd7mzRKV+xgewYftAXzaIKP4e2WBdnqHfYXxRPvqJ51Sj4QcDawVApjEI+\nvZoMv4vm3kdJlNWw9ztwWRRSf92XPvWBl+kxIoQhWICzJNJKvgx4UB+fTixm\nOZXgfG5UdHyi4V403DdQXBUx2H2DxKfFuF2csd9GnhUn3u9ZMor5sI+RA48n\ncxonb4cbSM39moEKH0OUw5FljDdyHc4o9ScjMOtaS03tLlRPqK3mdEZTjF0I\nUrYkn2hBfgeEKHSWgygEroiBKcbnKU3PfvQuxJgj+fQAdYK0jnLx8UDT2AYU\nUH+FHg7nE4HCdsgK+j6ekvs5RVflxAUlmCOa0p0O7L4jQDAOO9+ExHVDRtB8\nFwtqTUmCaWfm0jZu/0MqLWsvXYrEmU24MBTXp7VNH4gJNwFBr6m6f5UAA+is\nhXhgDDLvsdUcMW2NY6kdNOs4shXunRmOpKbhU7KYtQI0cXwjWaZ4BbvqKYlp\n4lpM\r\n=ujUL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC+yqVMKsShBTmSgtf3EBliWB1zdRSqEzz4TF7mbyMpmQIgXE7bZR77iFlqE3YUtbVYfuZKN2Y7XZS8SnxkyfjdcNU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.75_1582510521590_0.5615649210727975"},"_hasShrinkwrap":false},"0.12.76-alpha.0-customapp":{"name":"teambition-sdk","version":"0.12.76-alpha.0-customapp","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.76-alpha.0-customapp","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-GM3C2zVFhQ2qcygfh6BgfJBkXNkoP1KtOh4hy+kwZlH5EjAkr3sKzmYvrvK9qU2kbrsF9dzjqM4ahlYE/4Wxnw==","shasum":"c2542b677386f91281693b9619b667d913682219","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.76-alpha.0-customapp.tgz","fileCount":464,"unpackedSize":986944,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeUzJwCRA9TVsSAnZWagAA7FAQAI1qsgoIu8nxMElfNU22\n/WaNF4mNqsfvmnX6Dt9rSxYvkUdo+k/02MFy0YyI2f59rfm2UGZioTH6DEVr\ngnxcIJAqEKR+SaJM1qACivZbvzoSVzrLIls0zR4XJIa707ftOs5uq0PeBt7b\n4OuileX0F1KL0PYGXhSJG+Q7AmPFvQynSCEgEipeJdd8IEkzV2H8g3xDJ4jd\nhkF5kXXxKZy1uiRM15KQ9GyO+zrBwWYkEQcYMmluVgCmhYiY2MJbZKc2H0/D\nQ3sIJNmKPjU1JtF1xExKa+i5C6nxMElGemVIB9SXINAAKXqrsMIXrnx5jtsR\nCmDm8vCGeituARgAcQ7D/2zRhce9DycYdQHYPFHCWVx4yuvSMx60t/Iie8kT\nYvOGz2R9GZCzGvYtKG6Ijws2sMx4EI0FanIE20V5k4o3X8Yxr+bfzS7r4xUz\nf/5u+zLn2lbUXmJec0lnlAGah1TGGYHfpY65c1s1YM8zE6xQ3rDPFbPKs1we\n8Wf0geexQzKvWIEaKR1AioCClwXWmRG49aF2E8jJreaK5SHKJhVVQlLmCS2B\nALV4+Nh7NClMV4ZWopaFC9kpAyO6YHXPe0AfO2pBTJ+x1dXL+d5zhcQdtvGN\nwj2cQVnr8uzu9M1z+X5wYWI3tLc9Nh4YaJGa57QQ8aBvMNuLIX6/kGcFdLeL\n7uXn\r\n=n/Dp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC57Yx/VFm8bPZlgP9UjbBLPGImub1XcZW1e6Z/SqwzAAiEA3f/ZR/ReCfGAr2hNRqQmQzhjrWc9yPFFe+qyPW1Kf+8="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.76-alpha.0-customapp_1582510704125_0.35096947232611897"},"_hasShrinkwrap":false},"0.12.76-alpha.1-taskpos":{"name":"teambition-sdk","version":"0.12.76-alpha.1-taskpos","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.76-alpha.1-taskpos","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-9Rg9jgQ0wrb97zlqIujuy+UeCbKBZeDTLg+Sb1jhT051zunBr4V1g5r5MqfUdqrDgdol1Ug0kSuJPdYagz98ZQ==","shasum":"563aec0d18df98cfa61ff75cf536489fee763bcf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.76-alpha.1-taskpos.tgz","fileCount":464,"unpackedSize":984658,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeUzx1CRA9TVsSAnZWagAAlrwP/0G+nGt4ucXmxdpo9RZv\n1C26MLiNHEiqWzysFr+Xt3TJQOU9pLZf3MqFzyX/HuPqHLlt6bgjsXt7fIO5\nc/wDUyQhIFTIgVD7JYuNLTHGIWknqD1XfbQAc2u/Gk6Bz2DMP98K6D6sfoM2\nXp+cw11UpLGYq61AajJS8v3cqySqsxw0qpDBhnmJfcdjxKFqfdqKp+W+kdbF\nBbi64QP4DnbdsEs0NaYRxVMjt+bh2Xrs8EqWTQG4QV3qwW4SKwSbzHvgYJDT\nbJjp3DS3KNn0CM5Q/FE+8ebDTKBieraDtrv7Wf9hOdQtgYWXiT6TGojV7wwm\nRis8O+jeFbpsvqD1hnCVFFVzjqN+rO+IwRUVnIpbKDAYrGwhNl1SMRbOwqKj\nXi41sk4jk1FAs0DFAMfkJzR4oqqxyRT7wALQCr2bU1RfF1FLDKYfFZ2l9xO4\ncmd+NeNNymzWHpAT+gNIpjXuXaJt78rv7O5eSmMfhyCBmQB2EY/TM8Ugjxvh\nKPSKw12gZvg8ZF03vgvn10oxxMO+gtnsayUyWGCrGELersHXQN6OOipM8huC\nJYWGONI2GNYnETSK/9B1I2/tIeS2P6fbsHq6iE1W1xj8Q/RSzy84IN6tcqlt\n7k78NHzrvHnStPpZmIbHnQNPBB0F0L/Bneir+M1PryndPcog6ACBfsm8NYBM\nZvW7\r\n=gr+u\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA+jcgZoav7n9ngRp3orNrv+w8UbtuK47hF34124U7gKAiBF+yZ0a0IyxeXERQAW/RgO4hyI4tg6JrMp9htuh1q4dg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.76-alpha.1-taskpos_1582513269076_0.4058073388946031"},"_hasShrinkwrap":false},"0.12.76-alpha.2-analytics":{"name":"teambition-sdk","version":"0.12.76-alpha.2-analytics","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.76-alpha.2-analytics","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-hVT+Qu+guIjIslEJl5BrqlObhSVLqgCmnexC5ETKTYBmdjGWuIVW+ltr2AmrL+qIA/COnJr+sDf0zzHl7mA3Ug==","shasum":"1ca692147f13e5d9a2c1b067e9e55bedc5cbb1fe","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.76-alpha.2-analytics.tgz","fileCount":461,"unpackedSize":982125,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeVHcWCRA9TVsSAnZWagAAyvsP/i5By0AisoVBk64Ks1N0\nk5YnniIy6EUpCW/GPZ4UtkfYmlwRiMvkYhem2HMR2OnXkZIPDc9nNwqWfAaW\nRGTlrJZ8DyQ1/4kWF4ZkBLaWFmyFsdcI9floSRzpOzK9o0WQfpsnSCJzRQUu\nvOOd3PViQUfZ5EOQ3hLyc53v1BVXRmbE8M7uKzg8UTVTFEMo7K0sd08RUoim\nQKnbEAG9Y+xDh8+cM346Vp4Aj+97KlURtGvIcIQLvpMGQcqHaO1nD15IbNkt\n0FW7V5Jm1qZVjE+EGtfH1oVsKWOhODOIaF6TU7tT7VeboCN1dc4fdkstp2vi\n7a32gmhwVx0coZFSM2tT74ak2lzDBf1UpFSiM81PE/X2yOKqJPBzYxqTJ1He\nKhoAgpqlXIj4P2Oh+2n+dDKtIYWg9wfsVZTM7D6jcMK30/rMLA7mplIGkzvp\nq+333v0jYWAyM15xTAGnLwZtDv7uorNGdibN8gOdxXh8LVtVNdvcSGdV/6J8\n69F6gLsDK0hVlEB8TktK7MUkK5tEKSp9jCTjR7u90cWy4ZD4DgNVOreHPG6l\n2HWkJzM7wf1Ilzl1DqyBNA/+xz1yFfIxJbvFON40Uz0Q7HpMavJqn6RZLiBt\ndkK1J0MClzi0ky+oK6gZDVSWWZrAYMr4wK4v27g06Il/i3fUPII8T96F5z93\nYtpq\r\n=OuiS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDag/0T2W0pct/7vlt+vood/9gJdOCHxwh3oW1neUHBzAiAlzHf8LQtvKl/3ABAHeI80/0xOJs62IgeoQVa6dNL6PA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.76-alpha.2-analytics_1582593814004_0.5608221001893305"},"_hasShrinkwrap":false},"0.12.76-alpha.3-analytics":{"name":"teambition-sdk","version":"0.12.76-alpha.3-analytics","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.76-alpha.3-analytics","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-ZQ3BIyUMK7uO6QIrOgfYsLq9ob60+0Y5ONgOYltSK/eT30UfRoGakF27KBGS5iQzj+8mSVsx2wkHkw7UIsluvw==","shasum":"0928c8ba56bdbc5e6aa661e9c4a3334e3b7e13a5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.76-alpha.3-analytics.tgz","fileCount":464,"unpackedSize":984707,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeVIz7CRA9TVsSAnZWagAA4tIP/2Zufi0ZW+mB+NC/Tm3m\nL2Mn+SpWS0GyPgguhPWYk73nJZWeZnjZASjHLZ+nU4G91PTHIHDbp1GbKVOG\nM4CgrlIIKFpaeBRFjqdmEonabRAol2EGxnkhqGL07gLEBF3szJkCFoQDN4U0\nPNd116+5xiUdxKmD/3TFidTplb6XvLkQw7WSCZHyyZoBiEeUBWTyP9cvP6R2\nBxFYvj01x+ajIYOlOr4qFZUmr5AOa51hjREGIkCqUG8wuRZvK6JeuEBvP2GY\nKkavaVnO35sQKhBiiWfK7WU97Y+xqfQaUCYqgIkBuH/bQtfw8z24H08kAxvh\nmtnJO7FpQZ6bTtcFcy5vcnZEWX2TwIieX+Xry8hM8q1VRCc/XkUoK6/ziVpc\n6vbRflQgw+vwTeIkkcWb6eid8DujbCzwfc7LzHmhFPR/WK2blrTXk5qd3Oga\nwx2mRGXCaJ03M4Q0H8fgiVT3Z4Nm5imYwwN9P/DQgfX1jLJoOUixsIXxaey3\nHXpYPw5QGrN/QYRgzJuo3w4A4RwpyXn1i/BcIIgK/p3oBahwd7/OCzmu2ezd\nN3NlVLlISVXAo4eaTtxGVq9n/iHRu4KKfwu/eauYsInJG4QeRBVcXiZ7Lp/z\nnA9upxa8l9MimZP0MagWUT9aV+q+K1MgYezg8FjLj69duMzZWkndp/lZPaq2\n6kum\r\n=yhFY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIARuok8/ByfmAA5MX7dft2n/YJQVJXUq/90yg7qNPx0DAiB/n7qhIEiCwNGLpPQlnlK9LdumMFuE6/9h0UDuNzNjRA=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.76-alpha.3-analytics_1582599419289_0.7646608159499644"},"_hasShrinkwrap":false},"0.12.76-alpha.4-customapp":{"name":"teambition-sdk","version":"0.12.76-alpha.4-customapp","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.76-alpha.4-customapp","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-7LdjyH4bzrgZ9xMLQMNcWPNdrHQ2WQGu4seJlf78QgmE5+4Q1kNtrx640+xOBaYzoiYo9GnDUWgAQLhUloa1nA==","shasum":"547bfee1ab7f1dc9cf3375616fb674f45b81ef49","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.76-alpha.4-customapp.tgz","fileCount":467,"unpackedSize":989526,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeVOIkCRA9TVsSAnZWagAACu0QAIRu0ViqYI7yekmbucI3\nxIzyF0HKyBILNXo/upcvg897/HUCKlxKn06sJyec9xyPOvtrIiAg3aZjnP6n\nOUoq/ZkeG0QEvT64PsW3wbzeA+RC6QGW/ckmmtkX6Ma/Q34Fvbq2yc/UP7iq\nw9lPOJnmBzl91F1cy3g91T4Tt2v1kqkpS/YvG5Bgh/V2SQzpY3yQBm4ea6SD\nbO5AkbZinurKseZGB1GHcUOHIh6ynLhpJKK2x9QVNU/WPXedlbsO8MUaYvjC\n/YnoRkIoBai6eQGuLybJJlGYUdKd+2Uqy4vKf/SJRbIU8yaZ50TuwZOkAGGM\nWo6g5PCyrEMGbHl2HafhCHepp6nv+8WLYuQiZtDCMLB0CO2e/WwmANQUjVuG\nSjyCBJb53/x3SWbS8jMGIWVVPXnka29aVB5P5hKSwg8KFm40G+z5tZmVdHz2\nlYk5jN7jJ+i9fQn+/Jh0b3JQ15HjRTgBWiR70nlD0RTnIvG9I7BMxB+WhjZS\nyNr7NklpkXHIqzaC6Y9J+tCr21V2tHO3LZMvddys+OMqYlCiPG5hyvbvDRtK\n1icLdYEas5pHbyi23bRYXknMyUTyrMA2nIuPRi2DbaXq/TNIXMHARoXK186T\nftnHHivAFWkn52jSFWYEoO9bi78pG5+8473v61ZkZHXafQzRDdHyPZl/oTAI\n7XqQ\r\n=LWWD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDdSpP5Gyvm6I3j2ZzFH6wG8DnVK6UVkfj/a4F7N2yr5AIgMBgb3ZQA2u4ZD17HzXzLR19EKWoG2nNP8TqMeWxS9/w="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.76-alpha.4-customapp_1582621219657_0.23603144774212415"},"_hasShrinkwrap":false},"0.12.76-beta.0":{"name":"teambition-sdk","version":"0.12.76-beta.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.76-beta.0","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-YWHAAeyqCYZLERxrLIbgQ/gxtQ33AnLF2/w+gA/4rpiyJy0gPeRt6znuFWf0vGocVYM+pXsP9zDH/oVtWKHwkw==","shasum":"51f372e66f3c0c0a3049cea3b44de0de5edbe7b7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.76-beta.0.tgz","fileCount":467,"unpackedSize":989562,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeVgtTCRA9TVsSAnZWagAAuysP/RKqW7jnSond3L5xjyR9\nfBLOV5YfbkZ7amVozC4gtHI60KAy2ITG8EOvZvlEwC4Y8W9XDQd+LxlcOrT5\nhBSvOM2yRMBzV7cJSFSWbi8sjcPKIbfSTZn1e+lk5/p+QieVU4Jj+SU+q/hB\nyhHNgWOhiYuvQKV3kfCzRIAysDvG2RzFCToqFB4aizFEx+JtnllBTPXCg1Qq\nS7p983+cq5EMle0k1/mBCbftP2BD1JRUJzEecmmQ7mNYJ2mJOhu3GyTxsij0\nozEcyUpJKPZeLXp1nvH0WwjMU1xO5KhA9kcF0E3+IolcOQM9a+YeN/f3dsgN\nOtKBXNg3vhsrOVjsV4Hx5uCfxFnBLu/8G1qmZ0lhim3MgglYvwVbCjY3W+XT\nW/yrPZteqEYtTEtGgC/3AoMkNYUFRsWPz3oK6zHPw6SN8J1bdlYTF73pYFmf\nnsfbUBjZaq0wscbJUEFlyL3SJDkxNl3aCG1Im+2TgyH3YoI0gGhIOymYxXAe\nQ+mQNyh0WqmG0lwT58E+nKLVcYyi/Yl+1DkXRRlxw8N8bHNJsXXir81w+ttO\na7vsT2KrOibH5Pvhd/Xvhl83H1Hjqxv2D2CLCplq1sK5lVkGStQHdD5UqARX\nzO7x/WgNHAysmVWuQ3dZNFiUv/GOFcu7nqbCkx6BlQWyvGqgD0PX28CLThwQ\nwlh7\r\n=2EbU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFHs7W9ZJD3kit8Jb99bCRCPLtQs86maYwL+z7YyGTppAiEA+8h2X04abTDq1Csby2I/QFXdCp8NFZtxK3K5vvSd+Nw="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.76-beta.0_1582697299049_0.5514001850078871"},"_hasShrinkwrap":false},"0.12.76":{"name":"teambition-sdk","version":"0.12.76","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.76","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-814Lt64CNS7zWMeJw78UEXzKihSK5ekh+2kkaSaOhUB8tYmQUZCZRyBP3joqdfHqAURqGWvHrl8FQwaSZ77z8w==","shasum":"74d92c4f09bb748a2ec279e1f46c450ebdd6d39e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.76.tgz","fileCount":467,"unpackedSize":989555,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeYE6ACRA9TVsSAnZWagAABDoP/3YjpewtJfHgm+kfnszz\nKc7PkIDDmNLEAlP1EChEbfd1slXN0ZjWMg8mmwn4AiVP+kiA5seVjHddMEig\nwIB/QvCs7aJiiB++z1bJZoYlp9uFln1sXyTOeMWghqXaOOXET9oeQDWQC1A2\n2/oYUFgrLAfTM9jTiWinkm9GKa7kS9WiBcYKiPPrAZ8gbfJW2E+baAfkw9cX\nnufQtJ7A0R65EGKvJBv8ORcBB92V4Ihozw7ibS5MPbZLIsNXnOY+iQog3Kta\nHI9m6ADIGukk+YJp92GXm7GIGmaKax04dDfm2DzZvh+rHn6wblwjUadcJT5/\npN7xWKA4JckVeCAViZ6pUWFw8ZJXVcgVyL4k7D4KAwlEVw/bREPo2wDsSkth\nHymsnfU9hqEvem7owA7WTjFumYAKHp6TI9aACJTyJ6cgJbE1bes6UGY5uz1U\nQwrLmhq7D+FxE9BsSXds/SC2K4//vQ5h+Woq/7GB3vo6fwgLOt4IWeUMJgNi\nC64LVXoHz3Ix7UrLP8tVdWf//pQVnjA8HoGZyAnyy4NpAEk5pPJRLz5kVlxM\n9e6kdOUhiB95HDQBRE8ZoDeikRwqfyISMKp2kDE7Jfc7FxnoDa+dJqJMMuS1\nRLYY02pI6nx6QLwN2gIK9aJTuegB90tBSjkGyIT9h7W83es/SfntBOTiWiQA\nHY6k\r\n=2C7m\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFKx6eUX6ntKbpwrwCpH0Tltr/bk4Hwl2aZYmGafzFUDAiAIokepqC/3bbqox6pbSkx344sT2459Gr3Kg0L8ZEOOPw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.76_1583369855113_0.9318087291247557"},"_hasShrinkwrap":false},"0.12.77-alpha.0-customprojectrole":{"name":"teambition-sdk","version":"0.12.77-alpha.0-customprojectrole","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.0-customprojectrole","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-n1mKj0zw+SOCgWEh+HLOA08uuvbKcwAo8Um5QBSnb6eDy/Hwp2wfg/Q1jGN5gF4ugmIdK0bztGTfOxGc3Z0pdg==","shasum":"8dbc2940924ee9ec7de02b4407f02a28444ff75b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.0-customprojectrole.tgz","fileCount":470,"unpackedSize":993192,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeZbNrCRA9TVsSAnZWagAA1FUP/3O2V3Luw53pj8/UcgYi\nX9xfBwbWsp0HkN4+EE1H0KUbXMhxnVywFvR/KPSG2VndZETrP1QG6Jm0/pBF\n8eaDnTT3xz8BRyBMvaFOI8mpFVvWOc9rn9s6DTFOSpM6wfaSyvU1MDF/e6ba\nh5rAwsgIm3sJrl7v0jpBjnhsdFi67oQBXKWpwcjQlKygUgotJZjykYfbeAKv\naJVHXPcKwbYgW+YLOWfEN+jgqh69wtQi53BAe1vuXS+w+C4k8HAOxqcjMA9z\npL3FafnFZl26tCF2VigIPGpQf1xgzl/SvoJGWq7gyoyPXcx7SqNAMibSpipz\n8WnhBRLzEKDsOeGtCrEIVMZm5iQ6ai1TPQYkcHxFmgDlifaRPfZ9P6yp+bos\nhLfnQjaXBbOZLQFPpFPCivcsVEN8NAYHysDT3ru687MxHMeLsESZZTWuEwe3\nb7BjKlyTSyVZml23NbaRHuS5oMz2nvIp4k/hJ4E+hrg7poOhHuHki43EZjtv\nmZaGM49lPJLauDEm5fwaaX+cfjrqPWdfO+5tz/nS6NrS9eZYgSu6cDtQ5Ox6\nJcCG60ddYUYtACWGxW2qdNUsZCyEqJ141QhcKpRSVGBdGLi4XHXzTDm+LASi\nJxPVGpRwcaDvM5ghiTcF9vpAUqf67iZKsMQc1gwBgBsRbJ57uCLh/dSxwLP0\nBHcd\r\n=YXOw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCqlRGFFzWYUEUJy55+aUsctLCPI4FAA4I9jWFRe96nkwIhALsAPw4s7ybdjwTPIF9eauLJjBAyuly52vDow67I/wVC"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.0-customprojectrole_1583723370857_0.6749415122870388"},"_hasShrinkwrap":false},"0.12.77-alpha.1-scenariosetting":{"name":"teambition-sdk","version":"0.12.77-alpha.1-scenariosetting","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.1-scenariosetting","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-z9DESEfaYinagw7wlgccbH40UFQpeHHsopZBaHvdulLhlmbV1VZoYiki26AbpjxPYAxcgOzNA3okEprClEWEnQ==","shasum":"bd35c3be36d51caeb74b9d474fd1a521cc9468cf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.1-scenariosetting.tgz","fileCount":467,"unpackedSize":991057,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeZv8sCRA9TVsSAnZWagAApeQP/2SVc1pNW+qbeouqBDvR\nN8+/1nAaRT4/2hYuwIlf3wlvhdfqeHgXMN1dCamEqUWBfNuZEcR9Z3QCCkp+\nZoHct8NyhlFWJ47azrCxHQrefkFWRnc10xCB9yqNfxxmbhVEvTdVVxub0DdL\nLFht4EEUWn9n0bZByYtzEHz7sbtyWZXh3phy1LIamEOJu/mblL3HsiL1r/lL\n9UmVjbLiZ887tgeaQeIyW3fgFqQfZKbqRBzftotCC1nW8SPSE9azsflelRR9\nzxhJ34Am205ZNyDn0MQ+TQQwUOert755qtxCx4Y0DHOpyQNdakTbR7D5393d\nTm8qy5Ok/NtQrTXNk8++NNN1SOQt1+uQESgDfkIZGWJyPDCqRRF8YioM5KnT\ngy8EF60Ss9qqoAk5AQFPkiLnZ22RkZMhZURXgFfwvtW+Z1xHAHR3jFM7p3Ba\nJzGIoSbyYz8XUIHNbEIrNiPGW1g/damheaemzD05Ib5XeTnssQQYb85pBCsN\n6111TzYFBdY5D961ROEMyPARxoyepsw3gh1LdrA313GuxAxQIpT0IBi8qpIA\nBW8cVJJ14vpRlVaceVmi4w/q4VZG3RlHMgpJ1hKT7wHcPAmfxl9oVBnetV7z\nWWQTieQ8VHvLZmjYiUprhXozjmbUt00P6qyPD2uC3SIjD4EB3rdHC0s6ynF1\nw4VQ\r\n=Cmj2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDogAdaY73gJmpZ2b9kjzEbhVVAd1CfOp2NqOKkTcw/EwIhAJBp309PFBU23vwEFL64x6a2yuwFl3Uif6QhFlXoqExH"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.1-scenariosetting_1583808300345_0.7623025018975256"},"_hasShrinkwrap":false},"0.12.77-alpha.2-workcal":{"name":"teambition-sdk","version":"0.12.77-alpha.2-workcal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.2-workcal","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-ez/LuUsPvZj3llZFj7y2qqTWOoHUAcvCk7cwZsu217Vdpsn+SufJA31tE43Ks3UaTMyKlkCI4OUKIKjYm6NSTw==","shasum":"8f5b5b1a82fc7ae085cbd5dd1a6860ec1ba8f2ce","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.2-workcal.tgz","fileCount":470,"unpackedSize":992711,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeZ0FrCRA9TVsSAnZWagAAiqEP/iBMtO9QLzKbGUh71G5g\nWX7RINFliv46bnAZd0DFn7B+xOP/us8uTJ/qrnCOz70c+Slq4cU5pz6Dbksn\nWcUAXLomATgb4I/C2jxwh3d9EvGSjQyW64EeHKKbbxnKHhP/LpZzg/0TZavc\n4hHWSUQmuY4PYT287KbjZl69A5SKdSqVVtpy+RvouuYReGK5yDdOZ/ocjv1k\nq/y4c7e9UIpm9zc+mgYKSSjQ3i1mGnaHDrwQSKisXRqesrQ63LYo679cABq5\nnP0gq+JxvIglool9dINo7hgFyO1m0GBqRV1tHZfAXBecoOLFF1lqwH2AkyoK\ncPLlYGvFlyOjRy1tQky3VtNR3JOdm51EbsWdVdPwKdbF9JesecMEkjdCFu9e\nP435LXIoUCO7vvs0VIOYLo/B0wuKs+zo79C4O3afMSi8SzDLjccoFF4Tmut8\n8cRpacE5eewkzOMZKVj5mGcUXGevGDeQ4jAVk7trzKBRFFEpBtl/a/rcgNVN\nNOX1hQVIK3q2c52v8VgG3eVV/vHiiMTNh+X1kab3YQbyI5Nd6YFCX+urBf6U\nQ0NfZmdCr1yXwmpX3vJWlCF0jZDS7JfeurO1SldXKQQhN7oz/VOnUNNoIWF4\nUnJADaW9VtbaxC5DxvTdbGH9XWePgvG6+Oz+e6Z/+ObXnbtIAzxlHPgPWl1h\nIhX1\r\n=9XWI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFwPBuCnbdpTwTfrnlehJ3lxahxsYYc4vpTsEuRUlKYtAiEA6VZ1s115L9ic2A+g+QZzzmkenZACY2UOsthznLfi7FA="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.2-workcal_1583825259428_0.8912870376354483"},"_hasShrinkwrap":false},"0.12.77-alpha.3-scenariosetting":{"name":"teambition-sdk","version":"0.12.77-alpha.3-scenariosetting","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.3-scenariosetting","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-14qJVKmJwzfvEG1K614GN7LF+Mon2JiPn/8VgXLj4Wz6AfHY+YmzhQ6hMfkEnfCLQj37ptX1zVvpOitt1Jh+GQ==","shasum":"4ca517e8a03ad7bac5f5675693b2508bd6bd8883","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.3-scenariosetting.tgz","fileCount":467,"unpackedSize":991496,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeZ0RKCRA9TVsSAnZWagAAqWEP/1uMaW1IfhOsGd5kvABg\nJTImOh+GIXEYpgSUiFidRRLllmqRzh+VxncIeo6L/KS3XIujlyf2+DXYa8EE\nCIsq4dw6Vxx2TG6Q8QtAzc8paLdlUciuo8GeZ319AhznjVTf5DHdpj0Cs+tA\nAhVRSB6kAlLgz3chtUpM294FU8PQ2AcPeJLeaAbe1VWZ+NgPLiG9UEF/OwAr\n5JDZpE2CKkOmN/JaHLo/TDUPI43iu+QtK0ZRLkY9qKKyfkDoSdW+NX0MJ0Fs\nTAsa4YFkPyHtvFA5LrrMwBqFF345NKcEZPMd9/ZNfK8Ubke7a6iKjq32L839\nfBvwHisqicxwRuMc+4OxswxUvwuXPdkKmSQ2ZLrqG58IUoMK5werlXl5pO5f\nevv1zT1Mu6xtGF4+xtqDpLt2efO5a4bU+z40WDQUuvFJiD/CpHTspHgjysBp\nVieLZ3oTEEbeXMg/Un3k2yRHIbhtISZ2joFX34dm/MvqzcB+1qEky6zd0DBS\nNV0HzZDQYKRmMGB5ETzFC0zPEH8RvbCmnCUu8n3G25c2cWfDM0ayjc72x07G\nhUJuCmQaTPnvnbAQlDz9cV440PuaiBPkWUEK1sS7p2GGvQQtUpxVDCFXMAlw\n0QQ6t9Efio/CqjcRlN5Zj4GCi2O+b/Me1iwkhbazRDLvNA6OBkQiHrMGWl7p\nZvug\r\n=oWId\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCY/iU58sAnLxkhiXCCRNnC/ie3GcVgIaYGXHLC0my7fAIhAKAVQ4aDG8P7FthqotmTuL8xp+Nk1yAt/VCxXaf4jYct"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.3-scenariosetting_1583825993764_0.632978991849005"},"_hasShrinkwrap":false},"0.12.77-alpha.4-scenariosetting":{"name":"teambition-sdk","version":"0.12.77-alpha.4-scenariosetting","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.4-scenariosetting","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-ZB0k9fW48LhcK+JA9BT0lsyW54pExY//vTsUTD+uLLwtStwHAr8R02EFEw2hT5s1a+u+4fsrbMmrt/iAnx6IwQ==","shasum":"f32f12a7c0ed39b7b78f2bee3c6059713883f842","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.4-scenariosetting.tgz","fileCount":467,"unpackedSize":991500,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeaNWeCRA9TVsSAnZWagAA+XcQAKL4+8UaZIAe+sTpPbMH\ng5cRqj7FjdnGInTXXHjzgyAgJu2pK10Z7D6H5zEnnVbW2R1Zt6npWvC5gZlR\ngqWctRuyLC9Ee1588LQbkIsYx1FR8U6UGyarigPWPzxvtEwhAzYo6z1IDb0X\nNwFp0xQiDJ95GhlWy47mm/ppuV2S64HpIyxl81bkmCXtSyM60aYtufsw14vj\nS/Aqtu7sBo91HNfpVGCw//WjAqsFcOoo96095TuHwc0fvcaZvwDeLlJAKusP\nqvCi0MoFDoxZdTEHAuP6WwrrQZW7lcMLk3AFjn4sQ7ARkEl9Ry/KifhyLg0k\n15jES9rwH9wheWSJ6L6DUyEJ6YapJLM/mSyHHjQdry/7L5TpMH0YfAJ4WYUG\ni+bEqleJ7EeM7Z8R8ZreWdLPbSojXyiC0tu4q7vSyxNfO9HED9OZuvlcccnU\nEWi5uCwamBxKlmjCQkdPMaB+tHC9hXMesT0CcyfhJluoUU+crOyWCkkXAybD\nZmn3qo7/qwNSvwP1Abv3u/CnW8SI8cp64ssJdPEbsvjr9V/uOKM2RVNyJRnR\niJzTD8Dd9ZVGpGkJsRB5t40dDS5iOAU48wn8cltvBB0MwKgOCFIakpgK1vUw\nId/xIovn8AMSph+U30RfVQOqsn4b6sqPtYv2jrzS2Gv+EkLEZPAV+dFVUzAV\nJrws\r\n=S4LD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCzVwqKXg6N6p6bxBmncvnBBDINRZzzV6k12h+Z0AWIJQIgPBk5tshJX30KqvQqlo9zPYypyg/Eb3i+TEl6hQVKzyo="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.4-scenariosetting_1583928733486_0.333641850277248"},"_hasShrinkwrap":false},"0.12.77-alpha.5-priority":{"name":"teambition-sdk","version":"0.12.77-alpha.5-priority","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.5-priority","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-gRWTn2CNuy+uyrxx7TYnSA5mWCgc1loBA8FV5K7APIENna95LJI8bB8nLzxzpagzjXiXrO3QUm1rjzQovclT/w==","shasum":"4e03870d7bba817a3191df47cbec8e63e9fc1518","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.5-priority.tgz","fileCount":476,"unpackedSize":997207,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJea0rGCRA9TVsSAnZWagAACbIP/iz96qRNotchfznRpVKP\nkdLCV/xW6tWZuqGfLxfUgd6mvtINLYUDgDAcEwPWLoIgC5sAd0fhEC1cfHWr\nyNGgB8D2ZN0dBeeQ3qnfZpaTuLSheHq4xwUwECDLr3+hzYkFCMCrSLSmNfFE\nzkWg4mA+m7/hOqJX3957vaDXCID0bAGblsjzpdefmikBf/Xvoky5jaAelasM\nyKbwZEZFZgGJdSX8J3RihnPWfvCdfZved94Gp1ZkblDQz0ViEOw+dFmF7hZo\nG5z6PCE1prZdF/c3nr1/qqSHA4WMYXFcYkAeFAqwDZMmNaJzXNQJazpXfnVo\ng9ho2Hjjmcr/Oy83HP+JFwNeCse/h9vMtZAVTYhR3ycpeHx1vTatOyU0kfVQ\nes/gGBpg7ZN27oykKi1oGmAXv5lDnbOKrMfJJQNHAMAnopQmSxTvY67fZTsJ\nIVhdOhDoXOpfa86PZPXlFiYMjl13W60RIrrb3GuYwkTyyZsbdsV6J2HxxZBB\nxuwyuaJptqVcpMNloW2mZIUdgSJ5s4R2rb8g70Zsz4WTnq8D68D14SPYIjim\n6evwGoBVZgWi/Mpflqq46NEs5c3Pdhz9U56v09I90XZyb4Xh9uW8D0qZ4WPv\nw1NM2uiDQFAOV3QY5UN0wTGZ5Rxm6WtZ2i1en8MeWxm2sEuIe5L0hFSfhLLx\n2wEa\r\n=C3mW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDPB0MUPc+G3h1D+7/idO43NtIUP2dIsVLI01Unk9BYAwIhALVnTUucSi/xh625gsAo8shP05tUQ1XJcjJHO9la0NVQ"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.5-priority_1584089797966_0.9148525783351751"},"_hasShrinkwrap":false},"0.12.77-alpha.6-dinganalytics":{"name":"teambition-sdk","version":"0.12.77-alpha.6-dinganalytics","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.6-dinganalytics","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-3AjsHNtRZ/09zl+ut2n/Qx5D+BU2wjXOUi1GIZAipBATxPeD6HsBR2V6GUk6ubr+DC0HrVH8jIYNN/c1m48Gag==","shasum":"e6b5dc72935a97122e73d53e2a35286305285c11","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.6-dinganalytics.tgz","fileCount":467,"unpackedSize":991886,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJecDYcCRA9TVsSAnZWagAAIYsQAJqxMlr0bhRPAk842ofh\nhI1Re3jeIAzNOER4FS6WkHuVNq6k+vO7nLBw/eoucs+WY4AfYDCSRCYUkJlt\nMtRb2Dnx5iTkD+tpuiSnkn2W9howLME44Rdph6Ujhp2cWF5QiiwCIFlW1sL+\nlSakUrXO1qBF0oZUBLMOrK33X19aA3r1fwe0+9OryFpUcCuH6XLpQW1lSAXR\nsoOacFqTawWxiaDn2JTiMHhlusWI9qR7bfoafABt3mmLSE0ohF1CxYUtcEl+\nZan2Ds5CjK9LpRRqsAlBZ2IHBakw2VlyOWxpb3OzxUAOcnz48YtqgnEhvnXo\nOUgNOj6PXJOTagMrPNhDHPrOcDlmOPrHJqbVZfU2XFCEVMVXLssWHa82OiOS\nClxbfxm8sgMjeYDfP1YW3H1pNJcYbXBR3gACOwAmosaWL5QRhKTBpdZ8k5NB\nSFiHQ/kt1IgZ1C/GBdIQkxbRBj80s4KiWgRqkLpGPzAo62YlzRjtfn4jBPHX\n60NKonIYV6XFHPUDF376UpN5dXeVfpQATyP5F9JzCkCeOqKwFLhAUcOnMwUF\nlw6emSEWuUSdIJ+1lzkPj868ol3JAS8Jhc0ylJ1e/i0jBHgTssqxqfdjYjKy\n4GDoVTXsx4kOU1r62fd16NZ/37PUZINjJ9e3kVrLr4JvgPAJak+Rgr4ChpNJ\nqwhB\r\n=Iiza\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCbF6dIc5kJdcPzck1QEyUX49CGMCkL8xpLM6Tu6A0DSwIhAPxUy8sff/qElKIGU/k8MH0pmJpeOKEGKx1ZqG+ftfZG"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.6-dinganalytics_1584412187720_0.5778958058845614"},"_hasShrinkwrap":false},"0.12.77-alpha.7-workcal":{"name":"teambition-sdk","version":"0.12.77-alpha.7-workcal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.7-workcal","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-/zy3U2/BJOiof5ACTzHqxRUNlJXoaCCuG3jsDptwFB7UtIldSe5y62NF7tmR+eTNvOlKzIgSv00HfgRpX+4LTw==","shasum":"618059f0cd26bcf0ee07614a4d3d743bb4703bd5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.7-workcal.tgz","fileCount":470,"unpackedSize":994628,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJecJG/CRA9TVsSAnZWagAA8qIP/2KUGNPhFz7b7ca0WvFF\nYAVG1k+ROF+d2alLsnoHaFidwwogw0XWhDUF9VjgDAGaMHdosuJocejrR7cY\nQrZ2uqSwmxqUE+wiWhVOwSnCL5b2oTd6VPYcAY/yrntq3Fdv5Y3+QdnOkxLh\nrKSNjYEmh1MYANRs5c8DtgRD+/Mwg//dL9j3y5msP34xeLJyN0H2kAM5hpV1\n06zX8mxiPMW7SEstFdxKc8ofjhLOHOnwtLCzvK9+ZAMGCPBpoytQ8b+sLpBU\ndf4GQwFHJYnRHjbRP9QDSHAa0tu+BnqOT7wRuTMn6tylyCh5cTiO5RcEczNC\nDVS2xZEgfEm1Jm0whX+ZY3kfWrshwvMhSV5/INO0mJF/PEEmj7AYJjisG2Hz\nqC1g5FatJn5jn3yuDWg/YGglkL1IBEenN/8qxqWs6E/W0FEAc2lGrOt5CHGN\n9MhVpboYMxh+S2SskezSA0Y1EOHbyXf58Rby2mvNhFQBAsRn4Yed5YSs/E0C\nH5yZeiXcH/pTXW2E5Mkyvg/3CFbEpfw9cnZp0nY2F25iPf7RzQcqqT18DbDz\ndp2iL57UW2PDBmU9eSa8J1sCA3IstqdBowrxOAseBh+OGPLwRN+MzdJw4GEi\nJof/oR+kvqf7DchMrCTiE6nYDX4/d29ZVoltoU3RDkjrxDVmGGdZGKLqaH85\nEoGI\r\n=LdR2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID3azXWYWDO+n1YPvqgLpMwalrn6AkgX+uw8p1ws1PQsAiEAqpGRYRMGLarANH3E4abYM7DkPbOvYXHhmDbxtSBxlrU="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.7-workcal_1584435646800_0.12625603413491904"},"_hasShrinkwrap":false},"0.12.77-alpha.8.priority":{"name":"teambition-sdk","version":"0.12.77-alpha.8.priority","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.8.priority","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-h7eLTs7MrjPrtALuyejC9Squ73WDKyQkiu9g5C3JN1OYfGP9rQDkSiE//ZMWdId0HLnqP9+ULdC6Ia4SRtwodg==","shasum":"e894db10c0ee70439a081b4744b1d2487b5759be","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.8.priority.tgz","fileCount":476,"unpackedSize":997173,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJecYsfCRA9TVsSAnZWagAAk7EP/0X2hcCVXb+O0YfarQ2a\n7l7fMYPRp7OGIaJf8NoTqzYYjht6B8UsCv2InMZ6uqPt8DBIfQO4bGvZXGmx\nhDJTPhigttv6ymn32F8kIMwi0tRWzyEUzhPcz39IGSdoebF97x03bRjXRkIZ\nh7AX5t13rIpz4gz5TLJ/qdBfBc1qpilUx5pZSCiavcNUQQS1z+M5vqYKDERJ\n88eSccCq4R7JQSoAQQ3sJkUr4JwSfqEdFXd+mSZjWUrAM5RMPhyLFfRyt2pv\nqsEouvN1Ous5THSi+LcAeMvwzcmQxZ2tQa20PefMPCPuq0S9zkcKYMGGNcHN\nNbuwEhtKPVsbyQFNoJsaCDRoif5WFSxAhGmTJugKpzEfeLuSgQRhllvFoOou\nhLO3nXNigy94vgdit/43pRGCs0Gbza8qX7CwQWI2mFA5e3Dbsr6o0sSThC9u\nRgnZLquaPW4YLaH7plCJe/O/hsQWei7tgBp+oqjb81BeA0Mt+T/yaDE3u1bO\n8mQE5qNf3GsSN34C+wFt6IID9MlpwinF2oCbkNR6YRZaRb/Psz8E3B2vni46\nIO035ZCgyhZkmPmKI+qEPtfSc1aPdqcffg7iXv8EeKM6D4W4iVS58HGGE99a\nuIJzKTDhE5TSAjFxoxYccZptmdnByx2ukHgrDN8/4rk9JFUMaLuqTTjyBJyE\nmqrL\r\n=hfJL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCSFNdPuifSGQJlTOTZJKRnEvkXy2Q9s1oeV8ulFouIOAIhAO71pEFT45KitEON8oI+GGfDnOKM0NDroUu5B0eM30Jr"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.8.priority_1584499486762_0.9140361513378736"},"_hasShrinkwrap":false},"0.12.77-alpha.9-memberidentity":{"name":"teambition-sdk","version":"0.12.77-alpha.9-memberidentity","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.9-memberidentity","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-3LSW/c7NTkTjPOhd/02RjxSSzr1gG2bmZvt9Fsjrmvp8W7GpS4XIdoCPunzEtMwA7IF+bDqXzSXEB1MbsL4ceQ==","shasum":"ae3c258e87515b1c42f2035769902c674840b44e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.9-memberidentity.tgz","fileCount":470,"unpackedSize":995152,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJecZBSCRA9TVsSAnZWagAAcQcP/A2YCJ0yB+j1YB70tS15\nv6REKcvHjD0D3lvU7kBreYjF50JcgMJarkznCcd15wMC8fU9zG1VgUzs+Zuu\nV6v/ThHgmDywrGlouweDNWJY/W5w5QBW8tMKmuZFu1r7Z1Y7zgc5bcqQ+goc\nhz7R4E3aNeiloCNFUarZr52j6pce+8SoxWtP2tMmOExu+eW2y3gZwGd5Rez5\njOjjrq27pCiRnLhw5BhDbtNF87CiNFWbZGeUo8sofpGyjf9ytyaW2t1We6/i\n+sSe6v089YX37JyPsLzcayuZFfd0IaQ1ZvMOQ+u4khqkEcrZgsXd2SVFKFZF\n0qzEycOAPq6KGVM5pzXwDs1l3vmXgkrqDGQdB4Mt/o79tnwkQVQQyauadFSv\nBJpB9uXaKKABYwBOS+sebZSXB1Trk0O6YKSTsTf03IQde3sSx+zvv9DrcF+R\noHokvmCHY9JvohaExdWh6ovUAwIoziHKG11qKMZB1sJ+FbdTD5O/KxNYVzv4\n5LDdS/aO8jUL8NQA68xUE7Ixxz8OXTYOilpPeqerN5YNX2HukNAri0Ulf0xQ\nmC8dWjxZnRV0zF+W2myxNCYxmqWa7gwhwajAVu+bjvyUzqILUDtHd6W94H2W\nAwK2whGxFNoNGo6T4T7ldkqGgsAmbmxlJpaAE224AyjQYAoaz1dGw+ltuFyt\nVaES\r\n=gg5h\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEPbvzX58qyfuzFcVqScELCbscjhviikcpucS13B+Y9aAiEA751LI8n7Iv2o4aJkIXB9tREpBqu5PlF4+pBei6OEe3U="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.9-memberidentity_1584500818197_0.3046587646864245"},"_hasShrinkwrap":false},"0.12.77-alpha.10-workcal":{"name":"teambition-sdk","version":"0.12.77-alpha.10-workcal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.10-workcal","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-cxwNZK75/MIveQ29/LZcwH8K2ovqIoGR6N2Wqme1QJHWm/iY5PedL0vIMqDCSpXp6CLfzOqPkdTYMXd2B/rX2w==","shasum":"ba4875c869741da7a933b2ef6209dd0c59390355","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.10-workcal.tgz","fileCount":470,"unpackedSize":994633,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJece7PCRA9TVsSAnZWagAACLgP/2yZol9DIMpIKNHYNpl9\nZc1X0yF6r3jCLCZ51MUzTqpRTv4ZQ/La5nZ+M2q1sBlpbGgIeq0Iyv1JxPqS\n3qDtq1uzpooG2jDa39t9YTzDO6DKCPQhmYB1NkAVJtq79v87lwFC6FhwkO2g\nhJ+n87L/cLjMjgdVIYtSoCe4fv7XrvVUVEkQQ6qkL2A7giUhLdgS8wdb+7UG\nLAA5Ibjy0ckof5eE0IKb1rm3JY/RHKBnjsBckirdln/OChg1/wPSxZIH9I2e\nJZ77PYdMIZHrZy/QMVVdFEI8BFkslLySG6erBfbKhJV0wfJvdPoGV2clTLLw\nF6FcN/verzYEO1r3zzy5AKj+LzYYb26er5Pki4wmWqBSD5Y7WOGJbqsna4KE\nAfTEHOVS6pUP2CexkdzMjwLMfkqU8u+OQseKi45WAv6efCz/vijAIBm52rcM\nba8fM0BXt1i7ShIv6dddubdaJWPhqKrKf5+XafkShYwm0WOtgQ+hgmEaFFur\naBg+7tzh+NoJWVkGT7rCa22RGpsD4mHIdx9t/wyqo1Sm4FHwWB//lBDmcKZ/\nAmiv/dNlgeiPVNxaeZSX1ZCLyHrFKdMCgqET/wCHajHLAhXcg4cASJQWv8l9\nnKKH4JiY9gl3+aboyI0kGJhZLY4rZNUi3hhWs4EJx+W6pUUT8ZLkIBDChqOX\n0orr\r\n=9qCb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCPM7DUmMjiq2dfHp/cB9yD5zvWgWDGrgvPI3FKGxjThAIgMddozpH8r/vpHOTjJHyk3lN/cLQLb0DjYdZTkZYJlh0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.10-workcal_1584525006503_0.013794633491425179"},"_hasShrinkwrap":false},"0.12.77-alpha.11-memberidentity":{"name":"teambition-sdk","version":"0.12.77-alpha.11-memberidentity","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.11-memberidentity","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-xr6qaAx7dMVWPE3jx94Vsw4WU/UMSoBEvB5pePi+cXBvoQshrhrKqU/XzjOPSE5LBRdLRc/MFEeTx0QIhgU/pg==","shasum":"24e5dd974ef3afde70a31ddbd4127ebd3a8c6290","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.11-memberidentity.tgz","fileCount":470,"unpackedSize":995472,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJec0ScCRA9TVsSAnZWagAAV/oP/R5bOQeExs/CsqxCLry9\nhYnKkzuxIyOeu5dkbZkyPjQnh68qf+OuMquifyhN5mAlRQWeiRbSQv1TgBwu\njOfqtYglyQ8qVd/DJYbkwluEJjNCm17rXPvjo1jJkNBJ4+eKwEeTS9YEBmyu\nAzZDdidrTPyC9uRvLZ1GphVyIExd+S42MzSb2dSRSm14fqgx8JuxCiPX9Yos\nmJPgHefvMyKWFLCdJdxb1/bNU2V721KeabXbNp+dCSmwlHadSkaGBnlxQ08K\n0A4LYgR7HXC1J+u8q1NzwwxtKfkV3vkDeTSpgyjyis9qNjrNAaofCQ/j8WsQ\nUOCGpsWpImnwzOgzdK0AViIxlwr/2dOp3eSC8gz9JAMMcOLUC0PKIr3Kb7JT\ncRVyPcgmjaXbS+3dAcZKvWKWL2BMRtYnm90drssMOHlQMDBW0PMYtlh1nWRA\nnS9qsayW+hsHFL7b/jIwU+5IsJ32HkL0fWtW8muy6YExaBwhpWAo6IQm7V4J\n56fTxy9b2cAxnJlH05bH/vXlov61PM8TtC986hgBwvybmEvhBljQcNTJbcQj\nl1iqA1Vn84ALpTXvKeZaN9V82eGVPO+nHK2wLy4C2o9ORm5CiVGrxJVGZtk4\nfed2+i6MqJhAcPVOb2ixrU9KEICQYJA6EHALkRhC2VtedSCAUoWDqazntvip\nqxAK\r\n=ikdE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAZIBH5MREu/i3PNva8bA4fVc8C3oE2z5LRLQD9/oN6VAiBv8ENATgfvxQY4lQMSGJaAtCe6JWT4p59INiRMMQKcFg=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.11-memberidentity_1584612508263_0.7982396772710487"},"_hasShrinkwrap":false},"0.12.77-alpha.12-workcal":{"name":"teambition-sdk","version":"0.12.77-alpha.12-workcal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.77-alpha.12-workcal","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-UPLf8ZyhJmd1KxoiDF3eY8dm0+puvmi8nR2xFiAJUxsHVEpzBM3h6Vz/uGgaUcK4Z8OURRJovQ7R7tzlmCFNAQ==","shasum":"f61fb3ebc92cde12c30aebbe56562608c9a1607f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77-alpha.12-workcal.tgz","fileCount":470,"unpackedSize":994837,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJec0XJCRA9TVsSAnZWagAACmsQAJhknC/SojTunWHzWtfM\nOVsr1CYl1k7gIfJYpLYWINHi9u9GTKyce0Ya0qeWV1EZvsnRu9ZHFCbO3czu\nIuiv5seBYXfTmsmNR5baPyG5ZZrd99hgsWz10Yj+MWKQeT0hkLf8cpnoWGfP\nJKXJwRA+jKZtwEqt29z0AvYewTYBcJ9+/17Fn3ySi10CvF3nQkRXCJml8DH1\ng2/jJFgGOywzeg68g6O9J+03B7i4BrfrEobambFTQI4CWGJ+Ql32R8zJjY3s\nseZKE+TbMaZFsxu1w3yZF5rpd1qqOaXXMdzrqlt6JL74YLWaec4SlL9IDLw+\npbIEosXzSZ4hKvGxSIoaWtryEN/hdu/waj3xHzNW9xsW9Xg67ds5Y9Xbe0sI\n6JiKUOThLp4p4znNNlgz8vMvxefHdqPOm51RUGrpdXLGtLJhsfRBgLOxN7N+\nSPRErartoRPI+/FF++CNL6pBwu3ivgjh5SCUAO39hSDRSkaEf/H1ixWh5x18\n9Wr/K34KtIOaGgb26mGOxlm7XFOIfqiWDKJ23fpi31RrWxQGEnENjOv/kNbr\nHuGg31RWnGnKEX2y/3kRCMgmdZ8ylW/Fb2jGc+/duzAi62KtHEyo0Vj7Fe9G\nY8q4V78oMZ85gj4VSu7CqGgE4wVr7B6mm1H6pK3HTaqdjv9Na1Bon3I4hqte\nOOvi\r\n=NhIL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHKgVGa/cQtxjMEUkWPpJp3gxrS+Pff4XO7lln2aWQWQAiEA6l6201cGhc2rCtJ0JkZMpU5JoN66wXeI8i5hh+pCK9M="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77-alpha.12-workcal_1584612808496_0.5294617130866743"},"_hasShrinkwrap":false},"0.12.77":{"name":"teambition-sdk","version":"0.12.77","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.77","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-o+pxLl7tB4FtW31CgWxRXCmg44Ra7d8ZE/2eK7JdLhXzuxALTOP41ldz6ypzdoIsnTlu+JchnniFCb1b/vaQcQ==","shasum":"11701849eab15656b68f416f2ed6aac6de2bb8cf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.77.tgz","fileCount":467,"unpackedSize":991476,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJedIaxCRA9TVsSAnZWagAAdEsP/3o/HXDbdhhv4d/DoEox\nIFZFq/BKpPEcxXeMYSirZTN40V3SOy1nfxX8wZHbz8KesJ9vT2RA7Eeh7uyC\n9YGEcDBQSTlUsYMvtRC/xiIiqiZZcIjlSrfqqOKZnCTYFOyLMWQWrxHzclHd\nqX7aNAKK65rZarLS4mPRV62trdHfglkVa11/LJh3g1qoj6hKgL8/hzaXcBKm\ngzAMtyXz7TNE4TXY5gb4IFycavVoNu113lC07JaFcRBZS/tyOSt40UnhCxJO\nUpU/KE9RAsBZOBWbmaoIzchPL6JVjJNvCGEoeL6PhmDGQc02gWKYVm+bMubQ\nMZsFN8lWs+u6KT3yJcV9CsOIj2J0Ab6IcYScvZ8i+AD7FJMgmELFGvi45LWp\nSbxoIBY39WF4J6JqN6mVHrgdSeQJJm1VmFHk7GHZVYMuSurBPCxZxYgH+BcY\nihNCPZVyYSUGfLEHpsqH87Z/php4KLeOLPcnvJe+EHexyOIxQPqjm13N5kKZ\n/aTrwzIbL8oP9lI+qa4HLaz29wWdTOQEO5DTWaNi9ECZru6k1qe3oyrFogUo\nfG61mU34SjdvsyY+hIuzjJVazsGZ3awyVehHy7rNQ3y0KTN1bLSgDGSnjIg6\nseB34wMQ8veMt71ZqCG/6xGPi3OqKuDGwWlpfSWh/lMnSXHw7JyDi5ySre+A\nbzF+\r\n=fxgS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEbvom+C5MKcAFQwj8bRba0fGuMzZ+8idoQLCOTA7rOkAiEA5nfzww6XUiuFhagi9tlmeWdXF24t6Qu0kfMXKIMWybg="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.77_1584694961135_0.3809288828510078"},"_hasShrinkwrap":false},"0.12.78-alpha.0-aonesrc":{"name":"teambition-sdk","version":"0.12.78-alpha.0-aonesrc","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.78-alpha.0-aonesrc","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-aWwe5HIMUqNDDu5uewXZohmSlka1nTBhEoXIpa72Q3nMB/lRYOlLDsz3c4mQSpnlCuYg41NFK4S4s+4ezpQK/Q==","shasum":"a2b7280e35ff765a2c137a6ee7b7ae411cc20adb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.78-alpha.0-aonesrc.tgz","fileCount":467,"unpackedSize":991874,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJedIcqCRA9TVsSAnZWagAAQu8P/3Di5elUdyhZe38VTLcl\nKG+7ExiJwL+qogl2ze5IGIjq7DN7pRu/0Cpu4TwJIsFbL1ldw9qVqor51jbl\n/phkzNxts3MXJmVjJ6qOV2cT7lEdrPFEdpp0jfW0c2Kco+7aKN04OrD9ZUCe\nMCG6HPtYXqbOXsXtkRSxT0DZ9DbLBvGcRBVBV1h4r6LqNDzEBgZh/O7KU0xh\nyB3WkeVal3DEqY5qFDvpqRFvsgAYmJ5opXy5fxHTILJXruO9YtgtPlyT430z\nniU+glaMmaf0HYrqjEQfVFqi56ArYxe8XykctuDKZN/bv1Tune0Gmmq7gkzD\n09RlRs5muPzTxqqxc3JVW8yBws/VBDEJLSkOD5f95fXus73xYFfkvytKtV9/\nQOTyz42Wama3tdbC6gxyx3gG0oif7sLjApaJlUsBOY5Pu3cnkBffDZRkranf\n8RIa4hKeX5D3lcvUettfiHqHaB67gZWqK3+w+j/7CUtvwwRxB0gv6Vars59I\nL+rrlgVG3gJI7/abhSbeKADCB0tq/Ouwbfx58MNKebCtAvGJWvDypzCRNaKb\nN9OJffCcTU7kVtwMueTmXWX4gMRqhFjauqNxcZ0zlV5EpP+MZQe7KiurtdO5\nxGzAjNDtvtoNEjJdIBHp7d62DWMd50uBDcR3HAI+fgkGidd1NSHWZiDxIxKE\nZDSK\r\n=ZCi9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5NTussZjPefYSXnyZXW6yEMWELfIQDkyozmq8Bq4aKQIhANiQOJNnx7iQt0NlrfkMaB6mEhA2I4BnPhzhNvGhElD9"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.78-alpha.0-aonesrc_1584695082378_0.485029850039987"},"_hasShrinkwrap":false},"0.12.78-alpha.1-memberidentity":{"name":"teambition-sdk","version":"0.12.78-alpha.1-memberidentity","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.78-alpha.1-memberidentity","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-4gTIrKNxEILdUUeMfKNLCG77dOmXtvLFoZiqy6CC9KHmu2vjKdPTJIGHuZmAIrQORDYteUpVZ6fg2jt3wJdlRA==","shasum":"33f2061ba4e1c3b3ca5cc44b94ec382416430c97","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.78-alpha.1-memberidentity.tgz","fileCount":470,"unpackedSize":995471,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeeu8oCRA9TVsSAnZWagAAewIP/25hC5F/xjpky6kaQLfe\nvkGouCNO7QP/kj0Xo5ZHgbU28T5wYYOouKBwvgWWu+wsz5TQTdk6oOmWQ1Yf\n5ouLZErA2oAhg09rKopIqYu1vLVKTaKoTNSYzH7f88Z4QP/yI7Qf4z5JydZH\nRZ9dgo+dbzRcYB0gXZGmnu2TV59H5G8iLXjG0+On9TIF04eqNl6rlMdq4AC8\nkVo9oA1gGZnfVJNc4gj0OHPB/Kaw2JM37P75mUigitIUbxtCu6QVor7oPUCB\nUxFUX+KA5vlAXfXwxlYxdMovvrHxWTH5l4Fy6ZdjWAwOTyMT+mrlEga8TY37\nz3gU5BUS6Jvtw5Xlm3eR+B094TXw/jIkOZnVUUIVGEXNUhVFx7a/99j4erVb\nhd/+kgwiNbZ3dT1BJNiv3MbaT5zqokut8sb6gWQ7Rt8bRB3xavyaM8FWJm47\nI/YX96ngd319VsdMW5kqulyabKY7vzG4dq7L1ixi6SOL4et+uDp95BsoTGn0\nzesUciPj0DUzgYnFsvgtIu7IODwcW5PcZ6s4yWTymkIa0RFFjfd2GuV2NrZ8\nsdqUqBbpgAVj7qt5cWtJkU+HnB4ASJSeOzaTwWXaPJDVmmUCxClb8yyPksNm\ndFeMItBoAy9gxCrusDI/HneM0U0wB+GCfRuAEnYLZWl/LoXoKYyoZnr6nP2U\nCy5h\r\n=s5qw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDCZfPiayEdlXBiE2Q+BHokepnEEX+xEmTbv31E3Ob2QgIgZGMFLE3qM58+LvODiGf5U+IWiLYHnZaik/9GERrw2l0="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.78-alpha.1-memberidentity_1585114920186_0.9135042524314991"},"_hasShrinkwrap":false},"0.12.78-alpha.2-priority":{"name":"teambition-sdk","version":"0.12.78-alpha.2-priority","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.78-alpha.2-priority","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-o6aa5kC4UcT3fPBIaYKyCen1dTui5ZXsxePJWnNfAzMDOwkFRWTXP/oJqxY9D+qm7UYM6gkObAPStYxzIH5dXw==","shasum":"0a1e22ad08810bd765ccc4f7df28c7e49c254290","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.78-alpha.2-priority.tgz","fileCount":479,"unpackedSize":1001149,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeevAHCRA9TVsSAnZWagAAlcYQAJPToovjwAUXtjxxoeBh\nOk/SmYNtWPS4Ul+/LmR+cAYYTPAaDHxXpNgPfVgtyGsSUZ+DPDCe84g4+EjX\nTiEK3wEYNMMWjJw5MMJVGOsu68rUo+cQo3C7eC5UJf36IFn2NWkq9Z14Jyr/\n8Ss5xmCScXoMs1QJJoCVjbF792keyhcHycITpuhCih4Kh3KKftg6CBbBfH+P\nNB3ZTWm3GkWrPG7bgs/GvrB1ndlq1hWPR1/Ki7HuCwQgO+xTSpY6+XXsHFlX\nT27FT8Wm4z1MHY5pepf0MIBWKo8iL3hoXayPFafHz6Km0OdWpG44Ublmlvp/\nWYCj2EgTMMT+soCEjKUwv9ZfPFiJGIEIXDb4Asw3SaenKqtbJKT3zpqE9ihG\n2mLOWmwyDHU82oUPF+FkvVQSHJIa7piy1foQBkrPDUdkdBo+lTytN6uT5L5m\nFtVyqlCHx25xum/v7PCfC5oh8c4YyYMsxxlqlxqAZJ9c2Pof2zQ06xrlHEPg\n6RtJCoT3neNGiPZm+fPqMQiKXWuvwlmnKpxGdClqYwhcKg7jNsw4EyAHzROw\ngWK4nNsRqjIt7kbLCvyiXh43dC1SD1UyGjLB69bIDqSMnOKyhwXNURI0/UgR\nBPT+mnLaWJLx4CWuyrIM6C0DSDTAE4T/IhzX8XLXkzR2aKOUddsS3DdyCVoB\nG95F\r\n=/LL7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDgVPBLkFBJ6P8QeAf6PrWOQtknzv+OgF6zMbscvQMx9gIhAKaVsqIvdcPlS4PxYYqyvMrhfR/GdgQ3m+9yjEQ38VEh"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.78-alpha.2-priority_1585115143289_0.9243376581374814"},"_hasShrinkwrap":false},"0.12.78-alpha.3-workcal":{"name":"teambition-sdk","version":"0.12.78-alpha.3-workcal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.78-alpha.3-workcal","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-GrXlNMKah/E+YecIQdmHVawV/B4jmMNyan9tqQIk4GF5aThjvJ4k2QGHXBJ38Bkkszkw8xlRFiXYih91tyXGUw==","shasum":"22233caf1f1b607460593534e8d2172c219c2495","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.78-alpha.3-workcal.tgz","fileCount":482,"unpackedSize":1004492,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeevKnCRA9TVsSAnZWagAAmbgP/RPRVSgJzP3wquWEZlCU\nQ/tNWYagHhNx+SjuX3/FzMPVKLFI6sq0rPMsCnupU8/D3LMBOG1BMmLkaPUh\natUbYA+y5c23uAl3SItKqxlUO9CkbmyKCuptUbPRZthGb2VJXH2/79QRk3BT\nlt7PU9YKcDLEpKtsLiSyoRUKuiHNY3A7Qx6Vfb9TZjYLBJ45mglKL6isOnDD\nKJgj33Q34ma3qzMUHGZkVIynU3RF9O2ejaDqEXma5p+Rlsg5WAbolCjpDxdW\n34/0gz9fRaFHJBf9AKw2X7WzaSJCfNy0lJJZA967A9FTxL+2/G97/W4OSiK7\ncHNmRqVyFTz1DeG59ny7auZFi5RQHes/zpHyJejY4vs1TMi2xZpWXr0946vA\nQWZqoHFalWG1lcJS+fYGutJG/vyRJ6kGwWQuJ7A/HifPSwKLVaBf3OxAKi1r\nZzGJN9x9j/W+S8ABVUvAerfk3bfd1Y3QJsZXOu1H/J0qwe0JhmrtgnKpGLpq\ntSqDXUNbqUhDDOXgLbGLBmGLJU/kbgRGtwUfBOCFEON/VQRRN8ZA5VJQoWlX\nZXL4QXgIeoXaSLP1ey4mfdVspX33RYkQXSYbxQfRurhJbxkr/75vlqwfFQvi\nm1fjyk5QpxVA+xcXza5Ve1oQT9xgfNyq0FWb9t4oOVm152g5dQBfhKx9A4HW\nqDAs\r\n=LBjC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDzpfTIQXHTm4Ut3Mi6zWTP2MxOR+XqWd7pbNL46hWu6QIhAICUl2njL6+NhmQ3l9u6kWKa3/lSOlg6TdtyMzrRvvKI"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.78-alpha.3-workcal_1585115814768_0.266856233123677"},"_hasShrinkwrap":false},"0.12.78-alpha.4-dinganalytics":{"name":"teambition-sdk","version":"0.12.78-alpha.4-dinganalytics","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.78-alpha.4-dinganalytics","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-c3NSjv0FPs9c88VTdy0jvlCmoO40RXqBzfN2Ti0JEPAxY1bcyjYPtN3e1sxtSQ9U+BBjO8K6Gxrz1SJ2VkSrTQ==","shasum":"afd8504fe88692cad0cfe69498225e92b3d5ae51","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.78-alpha.4-dinganalytics.tgz","fileCount":482,"unpackedSize":1004890,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeeyo/CRA9TVsSAnZWagAA1qcP/2ovIgjBMDCwmx+v4fjY\nBHSMeB1ABfjoX4R/L2GFROGYMTrD1FnlfwrIiA9/T22FYu9N0vdrh56Zs168\nUejuhRK5pGtC0I+8SRCT8KVsR8sj4M6tUiHU/G69Y0dXlwAN78xKCKpAaBgi\nDb04qS9WyDl3Mk+DH18rV7XwvhSK4GczgaKqJqbP7VoHQXRu7TduQPslsIXR\ncIp+7NUoZRuMuTa+7Rjl8/B1lPIU7IfnA1kj6pqn+IF5lq2ei/B2Nqvopx/f\nb8GieoPbwXwbgZ9d99BOBRc0Xg8NzyVxsyoUNldOZmyU+QsCswcBadP2g2a9\nI/aN4/mevyeS0qAu6IjpZ5k75RSGgSwaoZ1tUEH79hD06p5G8m/f91Xgh9Uh\nNgC5F6vRQF0h6AhD/rq6TxFlGA56lFvl/Kpj5OjRR1yL1kyEG/XsVGMcKKgX\nl3lfcwlVcY+mxbk0kJGphSaOFBJ0e4BYk/yltoULaOoaqj+Q0GNLB6Kj6N+p\nvcn9BXamPSof440//hJY8lMD21/EKUMFaQKSNSkO/DLTEiYGardValIYc2vd\njHUrS84z/BAUE/spcd9iOwg/hWyPc1JKNPzomBvT/QYZMbDif4UZgYf7t4Ao\n1wbARYe9/NO3O0aGBp7xc6UmI1C6EYrxxLcpJKLYXvwD8RIL7tvua1dpBuxy\nGIVe\r\n=/fKP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCwOcREb7BZw8l2MKoJRh0ijre9yz/1iQ7bDNmx4W/A9AIhAII3fQmZGPihmcAxY78Jpqm1H7tuJXaMUmVX+DvsHwPB"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.78-alpha.4-dinganalytics_1585130047378_0.01975853910022929"},"_hasShrinkwrap":false},"0.12.78-alpha.5-testcasecustomfield":{"name":"teambition-sdk","version":"0.12.78-alpha.5-testcasecustomfield","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.78-alpha.5-testcasecustomfield","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-N5OsKu2osjjvZY7PP0nOjVhvPV3U4W/BBkV/NOnvzg/M1TDHxrJlw6Ep/mDtEDg3lTEnM9wLPrvWQSXLXIqong==","shasum":"df962717fef1d7941973f0c3ce7a666a04827d74","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.78-alpha.5-testcasecustomfield.tgz","fileCount":467,"unpackedSize":991602,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJefGN9CRA9TVsSAnZWagAAhDQP/RPcM6YzMRywAGygiIDf\n9nHxB5YGnVQKUEC25BaFBApqg5oF8D20ivE27Xgvan7TfVVRxafKsDOLBrsF\nNrgTJdaVjXek9I+whN0ptG7bq0Q/FqV7FRNCxCH8wr1PmsTouxSLrCu5/ygz\nJpO5rCn6j4tP1MaZdMM8JDACh/bmkU0JQB7dAjv6b0Mscxofp6CvQF3mLC7d\ngJU5nFK2C8W435QxuzDRaYqd/E5SIFsbzRRBSFuSN20kUnfzSOC+ajyFFIb4\n7dp//zpy+7AVpVG2gATbhEHG3Pu9euei/A7rH+KOdDHiQr2/FTDf+xnZ3P33\nQHDCxh9LOeJelypzb+UrTfwfCYd3Cgld5vIswIjNcANMHGwJ9WJ71rJCCZN9\nxxv4Fh5gpp3m+tr9T16RElohxgNGJrvXkNpkFsXWst8Yl4D0JaMOS5Wd1n+G\n70ZGfsOfySw85DmxoAIY3qU1clXdMl9rGRG3KCuhqQpWgEhRfj8t4Tty3XVq\n9/5p7xP7Mikd+SUKs/eJZ3FLjqJfsiGE6bBIWTY8DZZf51JEwXoPILwZV4DT\nnQHN3sIa+52rSBaEdQRXSJQIWvhhaA+FK0OCj/iWwZ3xIrMuziR+VFhWi6Jg\npnFU2qspk79ri3eCmJKCPD1n8nw0yo30bzuIhb+EkzAUJydCPQ7x5dfZH1P7\nBQIZ\r\n=uTbK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCuTWFHRla1CJgiKG0aV1c8xxH5LPGzX+Kb45jEjub5/wIhALtZ/SUgYWy2XoIJTahaiOLtRk04/qEN426eLcC6Zf7y"}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.78-alpha.5-testcasecustomfield_1585210237224_0.3486162777208204"},"_hasShrinkwrap":false},"0.12.79-alpha.0-testcasecustomfield":{"name":"teambition-sdk","version":"0.12.79-alpha.0-testcasecustomfield","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-alpha.0-testcasecustomfield","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-0jCCjZylTW4VY6uUdSZFouY5LvWPpxBi5ijHghqe/f91wIw/Y0sw3K5hGUaVGxxXRFdLOHSYswT61853sJgOKw==","shasum":"f3475fcf384d8e68665a5bba275bb7b9be044783","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-alpha.0-testcasecustomfield.tgz","fileCount":482,"unpackedSize":1004994,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJefHBhCRA9TVsSAnZWagAAz08P/RAOFHmuPIOhDBBOyPD5\nim9sDA6FcfdJHgq1N5WSt4hgZclQNTvN1noI/zsp9h5LvOeakhOU+oYPWgFY\nJf635lhCgvefeoze3yWK6OhxpFda1sxz5m4xT5+RzfBw4k+o/6YWpAFIRNaL\npC0FYDazUOSB4xYqfZNTxzlOU0CcfTHYKvAOPiBLTSEswH0l1AMc8lWvgy8t\nARKHH6tJId5AYZ0bLNXytkgrjLg6H/wHoLbvObCttI6Di8Huk5ROKUGCN1lJ\nnG3hoSX8KZi0iwp5jLT9BYVPTVL5Xil5fLux5Z+lrxPvn8aH9APVeglqCAjr\nHtasjRVcOkm6LshSkXOROJJf50zjVMrI+DisydciK/GamOz2Q82jP3Af37j5\n4unyLFk3TlEhypTlzWhJVGUqc3qgX/waRoxHmSd2XoVqovNuF4spf1/ThSnB\nWdXW153+Y8fGuFP6zoq1roHuYLmdVUuyl3EZPVCLQ6lcko90UExrrmZyyfda\nIMCR4FIIwpzCHhqApHQ+UiPXlLAZxcPh+4YK5SwcN7Li4bt9Eck9VOxY38M6\njfRiMIlUtZrQ/1svBUbXn5npWg9lvl2BuZZnXnTLEpaFjIr58vkgBk6QOyQD\nwjaFlhGZ5qzEFgE1DSZrrfGBMthPvtccGGdWGt9lVhl+Npf+Qirdy5hPbAmp\njkVD\r\n=J1Hk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDkgjLlSoNLaebTkcH6zcuhwBIVhj3PAPlgXREaFXbIDQIgAqPUpR6w7pL6qSSFaMSXh/hEW9aZxm1OFLwO9oUAc/s="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-alpha.0-testcasecustomfield_1585213537263_0.4167293715558007"},"_hasShrinkwrap":false},"0.12.79-alpha.1-testcasecustomfield":{"name":"teambition-sdk","version":"0.12.79-alpha.1-testcasecustomfield","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-alpha.1-testcasecustomfield","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-1uF1auKnfJvy1Rj9MYkh/7P781Wa11izfRct5eIWBbTw5LZ5371ecJshW8odf8+/Q+4HqQm/UAAlmA+iIFvh+Q==","shasum":"384e722b7e587fc982dac3830c4dbd3f531e98c0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-alpha.1-testcasecustomfield.tgz","fileCount":482,"unpackedSize":1005010,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJegW2dCRA9TVsSAnZWagAAz04QAI5spjGzfSxiW5aKtPbU\neCwQilP7jnqAxav5URRPFwuJbKNbNviBbXwIwiuXhQYGX5LX0HQLDBxwzUs6\nqTDzwl7UJJPsCMtRwn2RbyoMjugPjRxI4ssihE1GTuTiGqVFxvPkEtcLu/MT\nmqGWFs4A8C1XPpCTOpVLspi3IkARD+peRbkEH8xVB3L1rTXrnPav7jw9l60q\n87kzdB1SoDezkzzwyyp958SM6W6he0Vcr+w6310kIYkmcz4jsUmpBfg5XFeU\nWapG9gzvoF8IW5hzRwT19VmELNE6QKmKOW7mgjtj77SrpRO5IezF+QMoW4O7\naUZZzCh1tjkWYX4rIIGqa2v5zWj/Bqx5cFVNOGPLFB0EHi6yagVglbBDLNd/\nJixTmk2oZavjhuyipaolNORM+f47K+GDig6004jjF2JSVy48sgbXhhNwa6ed\naUNF2Cg+DLtBQlUYFXcVSYi2Lfq5IyekFQh9fpJK3SA8QwaEHz62VHc5Ol4t\n8EoTKFzkno2eQTvC+OAAHY1p6BGioAzyOt0F4RBYffrdR/RKuEUWwaNQm0wd\n0RcLpj6zbHi25MElPGVnFa5DPFRZ81YjDCLg6w+dgO9/6iObmm81SYbYY4wa\nr7neXlLOiPxcjV5g4EHRo0eTQPvdwnnc2FpKef0OwTYUOgVAt/HbvjDs8426\nATJe\r\n=FkKK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE/u20JHlNMos1j3ROK/lGSQ8FmFYC+eHcRGglG+OFmuAiB9tmFbQCBtRoswEPBH/FXolJFDFdUjxJAAaflgq2O2Nw=="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-alpha.1-testcasecustomfield_1585540509179_0.8222699383395251"},"_hasShrinkwrap":false},"0.12.78":{"name":"teambition-sdk","version":"0.12.78","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.78","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-irV7XXsK/BtZFgmdoBSY4HgKuCgcDiDjXcTWQ2scxDaltbRUHZgpmHdak/F+PSuinx4WlLOV/kz2HJhCb8a8mA==","shasum":"1415ecedad409dc5cb80a312bb6d0a3e4f790474","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.78.tgz","fileCount":482,"unpackedSize":1004869,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeg1YXCRA9TVsSAnZWagAAoa8P/A3Py/SRJXN49dIoYqAC\nW7Ai/B67WTxN0h/MICZTvIKy7PHvBCIkPbDV2O42RXpa7wYGjcPfAjHwy4k+\nYUgQoGcgBsbYNKJIkFK85126tbFfJFT5EUQyEEJp4VX80mhzrWCu2uWijo4C\nVaYQI/eQQ8zz02wHYbb4tb4MsWkoUDmrOdz0ab3tN21o+mS7C6ux6JIjJ4V4\nHFxe3GicycA/ZcCel0j808xC+BW1FatjCrdgVuQqk7JZmZZnqqMp8YBr3+sd\nUzw17QkOBw6/wUWPS7N+fzxkB7fPGzdh2ZBbzD0MbK2aT40A4BMWY1NamKIr\nUZqM9dEDHj4xnFR9z8Xs2JkK72o/MAppgxlm38tZ58OsI3cNY/fLtmRwTWQY\n5CaDUcY6hvi8fkRhhs6cIoz0nVzauq77AVBX2CZdO8e1iUnR2CP7eRXHqWwi\nWlcM3CT/gUUua9poPlN1JRDxzTHD7O7jrA2BukYJzKJPJqc8MIfRE5SoTD2m\nKi+EuTSfLs1ip+n1+IAPvVrUpoJCDDhnPzZ5r4A0GF7SY1IruZbWpHYm41nG\ngJQJYUaff8MnjWesAWnALnMoukwyuRbNFcturi4QueFPi2SQHW8DWZAYe5Sc\nnaJKwHVvyzWYy1wDnKiaVBuQYcEPoOocSncpA7zSLSLxJ7PHFx6C4zBY5EEm\nwhug\r\n=JYbf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDLkX67wFdK+dbJOMFQPIRYuZVGbs42XNT57X6fmVtbzwIgZLNLjnAWrs3AO5TVpT+C8VN+aaX4LnYMtdNdCvDxViM="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.78_1585665558423_0.8365764531841724"},"_hasShrinkwrap":false},"0.12.79-alpha.2-aonesrc":{"name":"teambition-sdk","version":"0.12.79-alpha.2-aonesrc","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-alpha.2-aonesrc","_nodeVersion":"10.18.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-cJsPUUxK0wsBHmMf078yzbRFxi6/PKXrh0ZwBVmym/bdYhkCp+a99+Bf6+5waeJA+9BceJ2xqUJf8KSWFM6AKw==","shasum":"92ceb22f3df52f57dcb77a6d341c8ea24f688cde","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-alpha.2-aonesrc.tgz","fileCount":482,"unpackedSize":1005267,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJehYGdCRA9TVsSAnZWagAA/F4P/A8NXbCWL7ULq/BGDxT9\nTmGfdf44bzZmcPXEqSG8v0PJw2XPOhtYdSXUY/tGuxkKhdQhmBayFwQd593i\nBljzdtDklLvTfjj2eda/1kHw/unnUi/qbdlx7m9lo45BNH/fxTjFlkstY9PI\nMF8V0voDKykZMUgZzNZ22pkuPyluudL4ywxVGbt6+SeEM2iQVA0tDRwNNgRT\nt+vndNJXO9Dnd0QVdSkbjffDcbmFW3pRLOvpEk+6g4YQMAsAHbnqDfma4sq/\nT8fnE8KJrwIKjqXFUk21+DA3d0ahxB9wmG1r6gXfHDQYaZbWwwtclzZQ7/tj\nvnL4IqrJzmF5IM4DDsZa2+O4ukNN5M5iKziLpUgOWzsz9KAaBtTQ/3HDBLpl\n0N6WznDxXgwY1eBsVuvvd1HxeOM/MjyvbVv5W0GXJfrCVXzqsNG0DoE/7sHl\n8eanddoEQ5RKKw1eswKfJlQr8jElMDQ1c+xA/nH9QRbBywww0lZ4BQM09Wej\nYEAkMEz7Wc4qxgCWvm+jpUv+todabyiKj/8RORlCZDQi0Vy7ycj9zeXkHZUd\ncKEZF/MiR5IHcUHg/+oUn8tMk8pvGzmU6kr7lxax9ZCCNKJ34RIocv5JQp35\nUzjY0QSoaAuxBBMmfRk+3fnLp8DvVbRA6rzWx9j2unItsayREVccAECI5lqY\n4pAU\r\n=SLdj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCAAjO2rJV2oWSI9SIiyTrniSnAJklCfiBQzA/ZwNVdKQIgdWA7K4dP2pLfPAtJz51UguzkEn9aaCbUmGdV+uPrjmY="}]},"maintainers":[{"name":"bjmin","email":"benjihuang818@gmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"miloas","email":"genesis.null@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"tb-web","email":"web@teambition.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-alpha.2-aonesrc_1585807773294_0.4865463929840421"},"_hasShrinkwrap":false},"0.12.79-alpha.3-kanbanconfig":{"name":"teambition-sdk","version":"0.12.79-alpha.3-kanbanconfig","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-alpha.3-kanbanconfig","_nodeVersion":"10.19.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-0sFXr5HsBCpB8F+sfD6/gm5vJYy8kCWbJI7zpRtcbuvHFBW50atgdDiJ4eGs3lpfZCShOXLBXOGCCDoPDDNaxw==","shasum":"4f6d8a4dc08746d4c88b7661a8a791cb76482d3b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-alpha.3-kanbanconfig.tgz","fileCount":494,"unpackedSize":1020409,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJei9wOCRA9TVsSAnZWagAADfwP/RkX2XwikI6r8UteLrfD\nHSfXSKprDm3iKEwVCar2NpLfjkM2jFQ8mQVSfstTRUnv5KJHUQp6iFhnj1vL\nz2EM+rb28OkDfR25w2AIiTg8QtSlXETEt47jVMwX4B2cTr3/yyNly9Ksr/Wg\nTbtnswMMHGSCTLr6P2VNZzcGx4t71QuMK1OL6QdHQdHqr1Rot1Vxnf0qjJYs\ny4Tz9aUpAR5WNdKxa/zDpuOshaekEWqLsAJijxHuV+TL4fVTW2qYXP2wSXU8\nH6O7Ofi1QuKuf3vCbB8Sue5OH8d4QlxLbPDd+tNE0vOJVK4O9hvPqzWSE5gv\niAcS/9y229qaIcMVXXqyWFc7vq3+AcN8KwtjVass8KyMa7qVk5YnBoxyMdSr\nkwRa9DiACv7hFulUFv8pUfowesENmfJzMtYCv5TT/kryPlwCf2puqFc2oiDI\nvl7b2zp71OI1mHelzwZePKSVx3sdeRHBMsbGvYZRvxIoDqLeShCOCD4tphq+\nvwYdVLGGh/RVeZNR9ctIdsJT+tPLCyD1xTLGhtRgXnAOfUzfnsxMVtcZR3Fc\nqDnVhbk7YrVG8Adfogyq9mdsONUlmhUwDtpXNtJXgd4Uo9OO2oClGVwwN5Uv\nK/ON+Uxa5jqPH83lMkujir+ubmdtHkAvdEjydu5fVC54nEQTEMmxifByfkiA\nl4B2\r\n=+4rC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCNiOK376BFjIkI9cDnKBqqmygP1DhIfBj5iep3BCtl0AIhAMw+ox0aJ8kAwOCgppPbmKIPTXghEutPRSR3QxVEzXMF"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-alpha.3-kanbanconfig_1586224142209_0.6116854592284751"},"_hasShrinkwrap":false},"0.12.79-beta.0-testcasecustomfield":{"name":"teambition-sdk","version":"0.12.79-beta.0-testcasecustomfield","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-beta.0-testcasecustomfield","_nodeVersion":"10.19.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-PhmdzZqMyd5Cm7EZV5faqejyuldhz8ZpSnVzhyy/nq9/hoaNpQfcG/z0rQLspdDYmRz8JdcQeOolbhmaa4I2ig==","shasum":"00e25823ce81da1e267991ddab5a7dc866f293c4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-beta.0-testcasecustomfield.tgz","fileCount":482,"unpackedSize":1005010,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJejY8HCRA9TVsSAnZWagAA/xAP/3jcqcz1yoy0yS7WlZN9\nbPp8Wyf0lKhG4kxUDndD9d8t7MfYQQfSji3mP/SwPpmUuEgfyauyuXWGx3GI\ni+4czduJmBJYG2h7fgU/iYW5yQwhQvXpx0h7kupKWgj5DlS1AvlVDEJ9q+cQ\nRzMDP7QpiF66T32/HCjoBoJUODCXWeGpSnF63huy4KceoLYEHsUD8zLlrL8t\nt+bMdCsw1Bq3FTqn9vuzPnnlmR10D4IOzi9Ri5PtVds3yNzg67dpKZtBJvbP\n1p+D0v/fHg7jounHERdKvrAhr1BVvaFx9lu1tPx7bb4C8KhlTpdcXWC2648i\ns4P2/l/ko3wo5tU967wcErjgxWAapRhVcIWqXs6siRdtbkcXwhbt6m3kjNhv\nu5lGc8cCHQaH5a+icxdBEgicgKJStrrKmpRdp2aAm44dX5EPWR0ki35kZpIA\nBasFcH1gkDbn4wxiIqLmuXz7E8mjroHKoIFL8TujzHyVzjNUcJihY8Jd3Qd5\nzeGqJLgSAFcsu7b1f/kcOYyJsMRU+JfGkPmWQs6/7/Pff83qnHfCztbkHFWp\nOB17rlYGu8rKHV74wqIOW9qT/3qaBS1oVNmQi1L1jMLjylq0mCGzuKnL/oLY\n1IJARhFeIwxxtKCXj1iuOZu4g9JW9BvHZHIrE+na1mjViXcu2enZfoxOfQN+\noItL\r\n=9Esc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDYFo6o3Cq5djMJZkzdGZN4FYHfmABRADMSiOI2Q7BOXAiEArnVF8Gc8OPA7//mdbzfwafeTeYKZtp55qEs2UaHwuUc="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-beta.0-testcasecustomfield_1586335494906_0.37424157494472965"},"_hasShrinkwrap":false},"0.12.79-beta.1-kanbanconfig":{"name":"teambition-sdk","version":"0.12.79-beta.1-kanbanconfig","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-beta.1-kanbanconfig","_nodeVersion":"10.19.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-FJY2JOneeLgQWjdO2B/TP2lVBLTwFSZ564nwi2AEdrAA/U+h937nXUlxX5sHjzKhkdJvUD1CeobqoPS4AD13tQ==","shasum":"7e3b7916b7ef91ab66201cbb688b82bb9b5dc6cb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-beta.1-kanbanconfig.tgz","fileCount":494,"unpackedSize":1020522,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJejZCOCRA9TVsSAnZWagAAQusP/22AFlZBjbDlqW1cKHLR\nYwrFZ6PMp819HptnwgwdCXbFwAnI5NZdpJMoknayuPp6X2OqA2+uy+p5HHuT\n1dLH1OU//yorVwjtU6jgCfM8KHu6gFuEjGryKoldfNz7dkN+5RBlGlajF9qZ\nd/J+nwkRtUIOpy2tFPJDO59ftqgDl9QTZauYs0mF06H5fU3fCh+gKu6fGxKl\nLbC7302BpW+8bJ/fvcvX+BPkIS1TXKabKT0QcokDV9flNu53mRQMMkMHkQyb\npkGK0lSfPTwUDZLAsqnb1GlUXwP/Il9WjsK9s6c06NielWFGcNikYQSsW/My\n29jPXs+Ag6NFegBAQGc9HDbi5GdLjXuilLU0JRXx3aN9PNvL8ZdabEota247\njhnrp1B6Oc3SWWcNg1ltRxYbYLdJfAkazGvdf3ql8ARFNcevDNDPkQeRfIrG\nVw1MDEedlCRqhxWhBn3CojRsyH2svRfh7m4GqTuytqBfshDgxsQUD6IkzLdP\nv6mzan4BudOyYAgbEd2T0IoqvRLbgalcOMLVjEWPJrtuqTE4ymWE7rUxqbL0\nuJkCKWbHf7z+2VAvPQGKfu9N6O2+62q6z3ads/ukxuqBxxn3HkoYP5qtih3O\nDnO2+q+mHOt8shzPb3Fed22HuDT5u6dmuNXycv3KT2PAWB5Nmf4muaOynmX8\nXOe8\r\n=wNS9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDgH38GXx+yAjoqNxE7tBB/rUDWKHBJ6JYV1ETOETLLLQIgBXm7iioOzbB5OKbpmL7V8IksyV/p6o6Bg3/wD0LnBKw="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-beta.1-kanbanconfig_1586335885544_0.8774139292312606"},"_hasShrinkwrap":false},"0.12.79-beta.2-aonesrc":{"name":"teambition-sdk","version":"0.12.79-beta.2-aonesrc","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-beta.2-aonesrc","_nodeVersion":"10.16.3","_npmVersion":"6.13.1","dist":{"integrity":"sha512-Gl6OMWhawfIMKGIPlRS+WEWMt16OOUBov+5WkoVQoeQRgar9y9frsG7ySGu3zH87jF2HzIfa/P94A46SE8pQoQ==","shasum":"ae658493dee8ed6006bd8699ee5dc6eae850708e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-beta.2-aonesrc.tgz","fileCount":494,"unpackedSize":1020899,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJej97vCRA9TVsSAnZWagAAVTQP/iSnCEdsWvvqE0IySmuM\ntXDpi8rgppG/0u6AL/o6bM1P3T2WwD6ymJr2Ipgw9Dsj8C0t7aClt+mzfLlN\njSN2qHD3MN03sUdZ4ba3xA/qNPC/RiAQXPq/98MTv7IiCSidcvhN9+J5CPAN\n533M74qdOVnMG0MgpNai77cAVPsr/dCNcamofyX8MuoxYezgBxtzUhIOGHIu\n6UIqEY2zhoILm8x+bCXxWL40/H0d1Q9S+iGao/j3Vg/YqSbGvcF1+4ZjYYYo\nT8iHVK+wtfcLn7LwLsyxH53OA3NecBWhp5bjWsWMi1MMFzQ+pxQ6EUgA+Ehi\nS8tcdYrXJPlU/tEDRAAF5EEpNnTBmfLpcDmEpFNvtqaXusqdqa2KbUxhPoN+\nCHOtSGHxYqBL+WutrCqR5knEmGsCw+dJf/341bGZLVsvrmv4Sj9MnPWXr8KZ\ncbEWA/2TKYHfjs6Y3wa8ZNNKug/fQWIOVmS5g3PJuzOZ1NDIQSRDf7sZpAh6\neCjo9V0U8PQFoKW9jNvZZn/C8UXi9mkklC6uqiYdmmGo+hv5zgKlJ/GjvLHB\nOkoWK19x5p34S5tJkiXS18OinA3918rSa+nOy9UVOjDXxb6yXetpZEqw1+dK\nKUuyEpTVjgXGzRfWKT6Kyqj1dtd7dYpINk2ekoEYRpUlrP3qbTck437Xr/pS\nDmFK\r\n=E5G1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG2M+jM+CYCG5hkGHKIhIcFzKDko29ku78nlVNRvZ1qcAiAqrNl8D5B2ACSX+DISBv9s70az2Nv4+Rg8RH67S9jOsw=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"jinchang","email":"chang@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-beta.2-aonesrc_1586487023209_0.4968563351240134"},"_hasShrinkwrap":false},"0.12.79-beta.3-commongroupchoices":{"name":"teambition-sdk","version":"0.12.79-beta.3-commongroupchoices","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-beta.3-commongroupchoices","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-rIUIVBlhE+lrvphXFoFJvA/pBKhf6Lf0nxWBoimD+7YbaLBnk1zD+SHuqx/wclZywquIm4hAqxLjAq9pXcHDBg==","shasum":"d89a32af54ace610b21394acfd9ce37f8cf0ceff","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-beta.3-commongroupchoices.tgz","fileCount":482,"unpackedSize":1005247,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJej+ejCRA9TVsSAnZWagAAAXAP/3eVhhFpLITyl98IvR4k\nEGoeAT/7hF6o5RY6EU+gu984uq7J/MuFi4SZcKzxW/iD056one6KMSrvp+7L\niVU5hLZ1Fw7kNVkw2rTGphFYNuJpwziFERbzA8sDHSDLbiBStsb5Naam8Lq0\nTrFkx4dxzKS+PR57Zd5OjgYLLDHWmXobv3MtoDxvFH/F3BxKScnqLp71/mHk\nNlTkH/WP+Egw22Ersb7PN5fzyWax4wjlwaIEIouJajXyJl/dc4t6vNW8dzzc\nAUnjR94Q+cMqJe/R/nYieudTo2gPODRlRQV5S8NikKP6L3UvKkKk5X8YkxKS\n4DuToNWv8DtsfNiBVH/6xdx3VU6Rqs5KFkzuj2Hxb4l/JHJ0awjaWc1gXzJ5\nSLTB/xVBdUAbhr91RKPoqah5kHuK4T90aj6ObyrmpkUFU5S3s8nYFckI66rg\nzrr50YmQ2ltjTC5XVkJDV4Q/aT7YeZbMZD27Eb5+q4kkxukIX9+g1MmOVLe+\nULWvBLJQuANoBD3JlpDXj9KMA/nutu5fWOm3j2I6Bcvb/xKyhb0Iexv+3LAq\nu4Fp9H7I1QfludRmmdJzm3ernlyitAEMzrA1ftnq6IRrb9ebhuNd0QzwF1Bo\nvbmZ1U/Dz/kyxktINtmAmztkLehSsgglKCajHXvA9ZkpYr0pXxlktz+FCSjl\nrVrC\r\n=KFbb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDapWAT6d/IZWLijjB1nbYYfB54ZEo8gxvefZuGFY5kEAIhANhwUdfciN/ljcp+MXZjBA+wJFSY6fuXjmNn0jXb4/ca"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-beta.3-commongroupchoices_1586489250803_0.010770954122342413"},"_hasShrinkwrap":false},"0.12.80-alpha.0-taskurge":{"name":"teambition-sdk","version":"0.12.80-alpha.0-taskurge","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.80-alpha.0-taskurge","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-E4yJ4sMGNkLyp1VZInIGoKNidx6uFYV1tsMGnbkxBEHO4GU+q4IhOodUmKxg5/Xi1dnXawI8+BqU18/+IKqoFA==","shasum":"cfb7ac4d2e357db423da2eed08ab6819f5536425","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.80-alpha.0-taskurge.tgz","fileCount":482,"unpackedSize":1005500,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelA3RCRA9TVsSAnZWagAAcYwP/2eYEsReoRhei6vGkhMc\nZ99LVpuHjIzKyyn2oM6zAWZL+CilELM+6VWL+dPrpF5UZ4DsUqifD3Rwc8lA\nutMsC5b9vjZLl3LV+SbF+ZDfVe7b2Rw1JABY+w3odIFlZplwQGcJW+PJ+fHC\najnluOTMtmrtWR5/EbyJBM4phbeA1Za7A66YDaFkYrgDnSwV+xeYKU4sBg3+\nupizBZal00NDQej/1YFRBr/RaD/6y23ybnT2f2gG/G+4aTb4CGMCLjXymTLg\n1mtmH+ofyW1zvyZ+mIPwpjL+x74RsSSikjUjzTxTbhrpPL2ujDgAl5xeJtoM\nTTnBijPdXF1sGHjObUUDXQeIzexiRdwU5Ln+9eJApuVGPjUHCQS3wFoMTIUU\nLHXdnnsuArzWWVi8/Gp687AS0O5iYfh//D2SB2PA47gR+Wwhu2RmxmjtmZWq\nZ5EuEEuuJX1ZYi5dKyC4Q1v6QFvNeQtEDCTnPZ1nb6tNy3xx6uwwmowNRAIH\nAKFNh+qlt2gF//2m8AeY5swwpicC3AxbSB2+emf1vaUUOIucATkIVgICz8MZ\nKYCSsbJwEl/CZ4shQMcMXLpEcFwGe7NiymTmkOmJ/71CVtRw2jXFPaUgSKbk\nkRPyoGLXBz6iOZpmNDAP5Sa85QmvoOswd+1RrN9hbBJDJ0M8oz0C0bkVHc8k\nWHpC\r\n=XuTn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCCnDfduRAH+oInSmbe7+kWwKp2UArMmqedRgb6b3fgEwIhAKE0H09TyLvaDZdtRYDbNcW7KBo652YTr5a1v98NYGo0"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.80-alpha.0-taskurge_1586761169280_0.20889157159430516"},"_hasShrinkwrap":false},"0.12.80-alpha.1-taskurge":{"name":"teambition-sdk","version":"0.12.80-alpha.1-taskurge","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.80-alpha.1-taskurge","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-llER8Z3gV3fPspfXI3XHp4hFhq83Obe62voAXupJYEShrgSYvWBspPvAl5He+UHn0nONxrI+1gvqkWxdx5mfGg==","shasum":"5fe2b13f2f178c7f3a67da08f92372eccc721835","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.80-alpha.1-taskurge.tgz","fileCount":482,"unpackedSize":1005499,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelBRsCRA9TVsSAnZWagAAAnQP/0neqOUkaI+GidZvT6FL\n8PqzMTV3HuzhfmTAPuIfORnctSPuEMak6VNJdmOqHNoiF+0D6ArarmLKrWXI\nIJnxOxvFV1w22KquWjplwNDdGPP03uomLYl8MLhVIoEkfO28ysl6E4EXlM1w\n0kUzh/1yqk+VKp5Q7cwQqSbyvy4vDQ/oA7bZgN63dxWN3o+7ZGecOOAuMwf7\nnVGmXSzggKip9VFQVjdt5VlrFLUicnH2PeGNR3ZvV+daAj/1MSulMHQtiTuu\nXekI6W6wKUS2tiPv5xUs0GNC3vaf8DCcTWUTCRO8MJIOr2YqVYQg7Bu9i0BJ\n0a2Se6dqxqO/JvBoAvEeVgEwS9Zuwr3KQf4hTKgxvC99K2hdr5LsJLvX5oI+\nD5bu2355fgxYyw0ljFajzGsY3fq+NKL+P0AFTldQsUxq70RdlMLH8TCDdhCw\n+AJE1MGkUzflNPyUmoEiHTMSZW99vnUGYp+ItsicpiD2j4sqbw+39ARSYwKI\n6mqecZxgFrhVAAWeHPRNTY1mPn/ZfmeC0wUR2SbrDQHOgC+lXscXhuq/GMJe\ndLjKkaN8KGfjbdPqfIW0/xGj63kY08NZTmbKyDKCVZhW1tPa0K8gTZE/toki\nc6dsS8rw2awSr/Hf+/eGdj60PjAely3vr1k0L/1/xArLYul6Y4b3uQFK/s9y\nSHVr\r\n=kBl8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAloeIdN1myK16p399Qr7MbhOfck/lbQI6UKzZ9NK5ZnAiEA8h0o0ri/yJDCpf8vi74eGt/s7FNFRov2ipI4I1+V8IQ="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.80-alpha.1-taskurge_1586762860156_0.019313933962494145"},"_hasShrinkwrap":false},"0.12.80-alpha.2-taskurge":{"name":"teambition-sdk","version":"0.12.80-alpha.2-taskurge","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.80-alpha.2-taskurge","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-O5wC9oMSn+YLLidXy4Mi6IlIK0Yu9Hlv4uE5ZV20A1xFHGFjPoV2TxvoKHFZEGHcrYHew1/YgXRX0jBlbmuuFg==","shasum":"a507f2d01eb8e3a4a68f245351af0bcfb0a986a6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.80-alpha.2-taskurge.tgz","fileCount":494,"unpackedSize":1021133,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelBnnCRA9TVsSAnZWagAA2SIP/j00Xs10RB9/0ZWkAOJh\nlrNGR3QExlP2BACPORaOES0RV5zyLshT/FBHSQn2G8cAoV3PmglwOvTAeWr7\nwulmHMG/9gRUwyYLs5/Sci6KsPMa6giBzf1RGjIq+yYx6bRD/QbfkgaAoSNR\nJZIFJ4WzfGBnuFgkbA1urfXoNUOm7+poN6Cu6gUgm1AdFsIVh5xYGW+updcN\npe3MoK3QFef50M+9Uao7PKtf5lN9FPG3265CdaFNDA0Mr6xIU3dC+JdDaVyW\nFMwIWIemSOYh+u+r+fU34lrkxdb7+Z46NFNgGZ4vWxJqLRYMkrfr3UA0aNQr\nh9j5szN+E3Eq352mq8iDOpr6wtP7uS4Cgv7OFfIwFovnhM+TWLVAEvV8GaGs\n8BM6c8rwQmsY7mU+TP756deEnzzYzwUMdobpewB+uZxI22jdcZqgxyn+mWCs\nKgdqk7Vny54MY7xfZpc1eGLxKj4Sb0s1qlHpTdVF/od3AJgKC9MhCIZncm3O\nMAryK947t1Zge8QQ87fFm/o/zy529lUTprgRWgFvwSKDBSc/gjUjueeneA05\nImOcW3gk/85TwsjpqiNWY3sbdtAMO2J6kklbAsD0EwirxTHl8q3Ef5b27tbg\nwOu3p2CqXGFdcXw4wzXFjW30tHVfThO8AQf1jBZEJ7CzDPqYX8Tfn45iB2Cg\nOjUL\r\n=ZQVC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDPpHCs20H7jX5IwZyihte+VjQhS1x+FFxDqoajscyDRAiEA/Tq4LED2UEdsDKzdjzL6dt2PEXuTXvhTLQsqY85xI6A="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.80-alpha.2-taskurge_1586764263392_0.10950358220984735"},"_hasShrinkwrap":false},"0.12.79-beta.4-commongroupchoices":{"name":"teambition-sdk","version":"0.12.79-beta.4-commongroupchoices","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-beta.4-commongroupchoices","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-603eCSNd5WezgswYekEvrM9LfPr0LpY/dJpMCdqaCdYP9y4PF7wh9U/pv27i96OZFX1/TNHgx4vGaIZYhxhOYA==","shasum":"e24a75567e63e1d4b30113eb907fe9c19b5b4f84","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-beta.4-commongroupchoices.tgz","fileCount":482,"unpackedSize":1008327,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelTVICRA9TVsSAnZWagAAW/AP/24cr1DRrlMfcn79sWdK\nWWQb1NgdAa3nCSI4Cvxemux1opTLaZBPG9jTcmJd/tRSlRu6beCBU1TTBISQ\nQA0vAi3M3ut0RollDK8Zo+240jfmZ3xSNnmmagRxKA6oRol9iCevmrPQLPsX\nlx5Hy7hsoW9EbEKXmyvoj4pfyezL660CklsgXCxrw+xNctrTefg8lN4TWPK4\nhuk6oG5b9VGQ3KeCdn1Y8rNhG4YMB22oN+ZyEq21Afsh5oKmOC9D9fwhn7t1\nkb1NI6c2CQrZWoUbJP/A3dmwmjuIXOg9tBBZfgLtu0KNQSNXoWgXovKskiJx\nEeGficwKpT5QCE+/Z4GiYaELS0lRH8eRDyfPmrLmRIJMWMsm00Z9/FgofZUG\nDUEXMWnI8tvP/Jz/dXSWDbY2cTHk4OFXi0iwnhhxbwwYa8rgGbpje8lVRXPO\nrlef/rEoXmTOnIrAKW4zoEwjLxTH61bIlzmVyGhV0eR4V38VD+Wb1sILopNa\nRMkCcT8/tZ+tSNXvDJPdZfLTqNGD1o6XA7CFnnDh91rHNC1XJ6+rOQ49mOJh\n5dsQcitSDtbXGgUpfPCVnGX3/zChBuXsL4hBGbdy3+wq8dD+sJiJA2YY4lSk\nLu5qB7s/Hp+QgxfUFeTLAek+yoZkiP9OQrm7ePezr+ffuVlsGvQRo0IFsovH\nTBTd\r\n=NOXC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDMhdD11GJDtcvChg7aGjyb4Tgv1E3QqABCuybAf8ZVKgIgKMPccdWEx4nLWUusLWnCmZPYc+l66x1kHETTfV7KWu8="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-beta.4-commongroupchoices_1586836808122_0.45081024239548206"},"_hasShrinkwrap":false},"0.12.79-beta.5-commongroupchoices":{"name":"teambition-sdk","version":"0.12.79-beta.5-commongroupchoices","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-beta.5-commongroupchoices","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-UngzqG7K2FAyHmuM/bXFzE897FJdouTSh45KbtTsh6nUfv8aw0a+hUOAY+tnXoqT0hX+H8iC9A/BC0rQWblINQ==","shasum":"f3c16ab963a20c4d36e87aae816a765faeac5f91","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-beta.5-commongroupchoices.tgz","fileCount":482,"unpackedSize":1008458,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelTvPCRA9TVsSAnZWagAAc0sP/RzQgFsTNqqai40Sj8u+\nPIOWeDr+M2yd1wPlIDk9WRO/xdSRU/5HKEnt+Y24rV1g/xKiS5TPH9j6WHy5\nGRewwSlpqIWwPqJpGcpSdWhZq2XrN7oGbrwa4wWBhXnYiMMQfbdvCsbsGwFo\nmdRjuWDBkG0ws5U7s9oemuSHjbdTwN5j6OyzDTQMF4PDl3iog5FIJ1QN4xu4\n2MBJ5PMjrW/i7Y5POEjQkae9hEkmVDRvAQaNaM3EJqErIFlvd0ARHrsJ/Hnk\nnY3/OKAsWvRumRJctpd7LiYwqYo0JrwLXWyAmB0MbOMOuB+ZZh5XtVT6gCly\nNAQvkAtvUiRLvHy1Mfjpb2MU/l2j8hYiTsTilbKhD2K42FGVlg75UJzfdTnG\n2O/VQhdHKbLt7MbMx7fcuCqJH6RK4b8Fm0WjrktkKE1zLiqe7i+liwFF7TKH\nUjTLDvYjeuzCK2vrgpk0MLgv/Mnkl1UQsvOMKksJEGabSkjXy88/yh5nQbaZ\nEGjqoyPzd1wi07qriUJh5Hdvkva08Rj2HQCI9+ohhIIZjCzTOqabVNKKOorb\nTvGju+cMe5v6chtl7LfgRFEuXZq+dGSycZbQ8dwNSU9YrSTHqvf8c/m3+mBS\nbwQZJnGiH2nNgR0SCi2L6Hpy4kLJYPTwC6hKuj4dbk/XRBz0PP3DlYA4W4PZ\ne6sV\r\n=axhU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCUKb6b1Tqsc4iqy7Orr0YxEMzDNHf97VaD4/LLdUW6AQIgBuB3x4iXEBRYuyWVfGOfFxLO/9DVw8a/pK/48n0kzYY="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-beta.5-commongroupchoices_1586838479193_0.3988731496418103"},"_hasShrinkwrap":false},"0.12.79-beta.6-commongroupchoices":{"name":"teambition-sdk","version":"0.12.79-beta.6-commongroupchoices","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-beta.6-commongroupchoices","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-7OG/qu8EhLOlRGqyQHQObIe8GtIUmjS4qhivswGkha8fLex9MkKbQYUsl6M1higOoPe61ixlT/lxGhHSQcsRJA==","shasum":"2bd895e3c9a8aa54ee5770d0e62055040d993050","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-beta.6-commongroupchoices.tgz","fileCount":482,"unpackedSize":1010157,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelUYFCRA9TVsSAnZWagAAAjUP/jJNujt1H+ZAxs079Y5U\ntdwZUBMOzCFsW2yapLnaRUBJMPhHACGCzlpXq+AtTx+N5hKqKlNZyZOVlIbC\nIx0M4B6Wcj/ZG0Wq5t0qXuTpJnKDljKoPlkgwamqD1/dKuFNmIpcPfs8OpXF\n6j86XkY1ZU41XEvvGmCAE7BGDPIN/PChluOy2CsL2VyCk217ZYlZxrfFbNCY\nvoTECF7Gpavh7hf/aBrq3OVh69NCVPGu2oxbLZcFNl/3uoClLEQBTvQaeEL+\n2D7dMQayX5eYjIU9WR4pI96DRiRHEhWnnkAEOwAc7XrhO0xNEXndzEuZm2cX\nNFegEwatLM+wDQ7Tvr8D3FAacd7Lxr84/FM7K+eWu2DvmaIi6642w+PamGh5\n0E3gZJYGcCtV+oE9/bmj6sg2e2drITCHS4ogIVoKuNfFRBeoy4wCuq2sAJMw\nL9vsKn8Afx5BaCYHAGh2xhuE9pGf293bXvZ7ALONtZGjiG8LaYhgU/fv0Oey\nUHJUwlw3bvM6ANB3qKnCL0vNbjtFkCGi7Y8d0IkZguhsug0pm61ltIBL4ECJ\nwciY9Po6ANeuc79Ak8s8PsOpvj/mpk7+g6xHkakKlxkEDg9KOTyLkypsMLm9\nOlYK622gFdGTuHYxnTLtM/6jT9vT3h/uP+nTp3oCuondLMIkSVl5mXJmjGH7\ni5Us\r\n=Vp/5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDgsuO3YrsDZLesOIHWOIc7/h5gKgDoqYtN7ltHnZZCNgIhANdV5C3nDdxuiU+PmcgKPllIets+16GdFA3BM/vedRAF"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-beta.6-commongroupchoices_1586841093085_0.7447849012973224"},"_hasShrinkwrap":false},"0.12.79-beta.7-commongroupchoices":{"name":"teambition-sdk","version":"0.12.79-beta.7-commongroupchoices","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-beta.7-commongroupchoices","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-LNJ3kqmIbuWzA17Z6YPIm4ExhqH88AmyUpjpancZ74doVcJ/I47br6ZYZQXyfhXpuCcRDl3c/aN9c+ARMCTHYg==","shasum":"7dd24fe5d6c0b125c87abb6e22aa8f717af6f668","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-beta.7-commongroupchoices.tgz","fileCount":482,"unpackedSize":1011067,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelVHXCRA9TVsSAnZWagAA/vIP/jRj36HYu+Xj30AdnPk1\nHW0i+1vrAceFxhGpvboM9RBot8QBolvzHOYO4UZmh9q2onns6rl0oSV6lnae\nQLOjJ6NGwZ7dgIVxAUs314B4YIMfZUPpoxHUZ/ipGhMm0FQJ+H6PsOtrw7bH\nJudnIb+ZvDJa/xNfwF8wRGv7NmcSuAr36rftV3HUERiE5HsCqaL4FyHNYfYy\nnhk8Ha0BPsxNy3PvIAbP9lqcNc+FDvg5DA5FRzUtj5K8nSaRkeQnZBrhPXF9\nx6ZghBhZQWBf6mP38YxJxVcKziV8NaIHKV8vCRqe3aWW7Lp4DzIJrLmy/uA7\ng0wL83aZqmgLcD5CuU4GlRDIC3Z3qmgoxUNBD22wlR0otrgjxaqiaxJzzR9P\nGk+oVaxUcCv3u73mO0wVoqVadwOOnls/Ca3JfO3+lHq/RNGrgwtyqPqqP+2p\n/dL/CpMpLn13m4cllLs9ggsV+pluwtEPXjyMUswPmNIXQL9Lenzukd9vsV65\n+BePpR1ta03qsMYJRg2kw7yy6Vyp/6H9O3BdS2780IF5YD5bIhhaiP76902A\nNhk+J4UMAgp064RRF4ecR6G3CR3En04+qMKtlCxGxw8xkAkXN9Zbx9ZvhTBA\n3g/qHdEw0PQNpFYqTsBIS5Fue1dkn1utEfdKUQwlsgsMt7puAH5WdnqTmMMS\nKNqL\r\n=A3MO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCIB8izK2+3yeCXWKh8M1/K+wRfYEZ66dWvm5GbZXW95QIgBGXJkOkr3TaawOtx6gYHIuqCd6JtgrD8UfDi9wRlu5Y="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-beta.7-commongroupchoices_1586844118894_0.5267638929807736"},"_hasShrinkwrap":false},"0.12.80-alpha.3-taskurge":{"name":"teambition-sdk","version":"0.12.80-alpha.3-taskurge","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.80-alpha.3-taskurge","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-AP4OSkyTzuQNjiMnfXC7Zpp+r6tHYXh2pvQEuGmOZWPMMGWZqe+AR2+L9YWZatGbXpvcwt7yZmjlUmV+Bk/RPw==","shasum":"3b3e59322abf6ddb41b9a7281cd28951a23ff6cb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.80-alpha.3-taskurge.tgz","fileCount":494,"unpackedSize":1021537,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeluQvCRA9TVsSAnZWagAAKxsP/1oXAGph5DN/l535INU2\nCjGKIWULbsYRT1zqm41u07yi4kAvuYzarSIDfbX4SzrLKmQ3WniayTWcu20k\nXBsVH/DHt08ZtQk6Z+LmxX/1y+RmKqb3+5uCyv23LlL6K8GWlTZoHsROJGMH\nKu4WB3MVcDMO8fNNWc1Nd+bf5Z7mhKwM2vSetNmwWx6BancSgFFNO/cd+cJI\nK+hdylP9fYO7IT6RCd4K5/4dZPjr1xQ0uQH1mGWW2KxIjCJHwFH0L7sscvHw\nEEj8tkSPBeoi8KHhdPQkhKv4CVUuAaecLAA1nfK05TRIK49tWWpTbba+N78g\n8VJkP83vIS3JIDWUQEQCrhVMRtCzitoFIXzGb5VK1CD6pmFSpsa1+oB/Wywn\nY9MKHty32uwEs06iuyko6B9J/OpPGV4nKwRQ33clUW2M8jQRbr94Mv/qxZUP\nBqxUy8kbQpXMs8d4TA4Osr3ulzcrgDU8keKOPO6lNt1fHCyWGikZKCBKgPlc\nb3cM/kVtaaJjKRc+iIeGO2hGN/3dwrd8Uu5kB9sM4YIspd8M6fLv/oW7Ch5b\nrDP7EfF2aM34ZaGuT/GVkIgQnWBdqeo8Bfg2wksmFRH7QLLiiTFIlnlIsVvQ\nxAK3mbjq+MBWkjxOybJ1pcXQlMKSw8ir2zgrIEZuG3IEDrlV1ZFktJAmGa38\nxeC2\r\n=7Hw7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC1/BpinQbhlQPavLV8S/8ZnOVhqeoZU4FJtZZN2XG0yQIgGc9jtWPhKHRkTnQhBqetKdNxy4O2fw3yi5JKMt1BD+o="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.80-alpha.3-taskurge_1586947118480_0.1777358481619722"},"_hasShrinkwrap":false},"0.12.79":{"name":"teambition-sdk","version":"0.12.79","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.79","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-mcsrWqPJz6EWmVFz0bn24EUDWnQEkDzdQJGNB1Xfbm1BDxB1xekCaR3p36Xx/D+CJnrC06webpRNf0lMoTw8Xg==","shasum":"eef159d57fc9e820a1039d1eebb25901951bddc8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79.tgz","fileCount":482,"unpackedSize":1013400,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJel8jDCRA9TVsSAnZWagAA7lgP+gJ+Bgjz2aDOTQ63X/oc\neAJg0ACEy4ft01e4PhPpnmX+zZaZ+vuick9YtM5FQYphTAvD0nD0YnSdYS53\nZ2kSWi6nxSKLCgzciU/E8lsSGp9h9cBlPeAedQ0SwerIgsGk3rFgyDUl2QpZ\nXI6N7XE2ZtiNb7ROYyb/Qnx4gVPLOvg3H69l8MdB6sD22wrinRiKGjoppuga\n/MWwkfqnId3UYuZs4QkY0R4D4cto3KUG7OFe2qvzIR1EoEQD8ELGBJxSJlND\ncZkG6FyyaEOIAexBcnQ4gD8uo5jLosZPyeI/30MWpaPr26aPcfed23vYaf+b\nHInINB5LqTYvbhbdhRx0bRHj6HIyFaylPeZ0vlTiOnSBEOvDaC14JWhlvBZA\ndBktVZE4moo/oBGqWzE0YnpDr1p0QJj4cjENsTsfP0Q01XYQ/6/VCOkZ3whI\nvTEh4eNeinyyaSllELTWoxV79zZ4vekS4uVcCWN4COIf28Dj02OdXeZQDkmW\nUfwgKMz0SGLi8pOO2L3sKCZAcUIH/zqYr8gkhQMy0fR8kZnmXeeaXsa8bbsE\nqjLnpgYJzATJTnopJ+LI104B5DYYcBUKLz6e1ulJ6dcEDY+Q5Vsj8uTwxKrm\n1UDpwVQOLqy5gDFTaakaZt8Lb713jXoYyFdhytlnjIzTXBKfcZ6Jala00zf8\noLvw\r\n=Naw4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCggz4HXa/U/pTJLt/cZEyp0K0gFz7n7Rm+osmcMMhbeAIhAP7Qb9rIMqDH55ZMBJ5Wr92NozQoZIu0bIqIdKoc77Tk"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79_1587005634982_0.8231129360917415"},"_hasShrinkwrap":false},"0.12.80":{"name":"teambition-sdk","version":"0.12.80","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.80","_nodeVersion":"10.19.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-m4M8y3vEtzJH8ekOfqSDi4ChQWRAoToBAJ0bmktzfTGLJLErfzO2BEXAkESMZvgDX9HyKORL2yRIqGj6AL7gSg==","shasum":"077b524e3ee8f554cd82475cb15d45a8b0a687c3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.80.tgz","fileCount":482,"unpackedSize":1013400,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJel80zCRA9TVsSAnZWagAAqmIP/1sMHzge73hZGwvFDlXj\nbGpR19903D6CizLI2ThOP3dOpDdSUZrWMmPxaffLmx3wND8e3ugDCfG+lQDc\nf7IoHuXbE6NXFGdmoA8/oEiomnh/sYI4K0k0JkgUfLX4WsUMcrCN71ik53jr\n3WdS22tZAhfkObaT28L/bP86yC+lo4JGAtWFvap1Sn9AtLECbJAontKWwccG\n4PoJB9RYogyPNwp+jqtPylPYDGgrSRRUg3iUZbbZERvUQM6RKSoXE9PwR81T\nAzWSLxovZhY7HXENFFgKcha5yvMAR8wD9ARg7Cu2d9QpGGW/RNK+XCLYfGIN\nB+sQjGQ+v1Uwgx7+Pcbpa9fQa4g/xwL4pfkcOIMdBJFtNlL/WroE+VICqzkP\ny2gEmI7gsOAR7q7XyECpFmJULWrmyqTdwnzvZBW1gwSbfxCWcIcGkdXDGF/p\nywRcNQpE2taOJg3r0gFHyTKCSJpdGHu5DQs89hWKWH4VO0VExcu6mbQosPBL\nKRS+H0EI3EpxCC/C/HMm1Ld+P04SI6sgB8YGjn9daZXNCGnt8k/tbJGD+g/O\nws9VGBXBhX4DntTdQKB3kL7mNJsEhsqpJFPJgWc3jngGgsswyuRNV2fuQiA8\nhc238lUFyfGil1lCg/5lfYy+2Oao6FWIyRSxCF/k1Wet2bnwwH9IzXokvumJ\nvKDS\r\n=nzSl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCXYFzDSjSeHkVDmmYxhQ0GfN3eNgzYMdvL3MHP0Dt8jAIgPef8yo6jNmkMAhI7SE/WfEF+mxY8brtIma9kM8dRBmo="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.80_1587006770580_0.5874664068310669"},"_hasShrinkwrap":false},"0.12.81":{"name":"teambition-sdk","version":"0.12.81","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.81","_nodeVersion":"10.19.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-ycQl5HiiRl54Dgblb3ldR7vkbcZ5l/nG0GXLZFdVUXpZ6tqc1g0+d65eWzzvuqSCeYTs11DjdIFiuA1vFjk/Ew==","shasum":"4f0eed3e15ca70eec57f08207d1457fc63546258","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.81.tgz","fileCount":494,"unpackedSize":1028919,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJel89aCRA9TVsSAnZWagAAkcAP/34rA5aAaNHRZ19aHThk\ngcBDBUBE21o7rM+Ret2SzQvtqpdqcBqxQ9u+xBU2xTmmy7gEH4ERrY5tZZIc\nRi7hizTrhpqd11QwHbR+Snt3PMjHjHcSvEX/K7bJIIzSwBNrJC0ev1PYMVuT\nLQCIGvU593glQoVYbFJ4KuHwHjEOwjKvEwq11QEcJyL+DKNOpcQF4n2UW0aL\ngLZtLEUh5z7P/pRhDWzDo84JFyMEdeUb45iW3W5wTXAreVk8bD3bTWVZ7Yei\nzSGNUCJPLuTo90plqV+eBgGTMqizg7PT1V4pV7v7pOX8aisxa99zo8sVNlYx\nfiF7kpy6qd8JI78oBHNaUfx+iKkm6EhvfbdPLMjUrJghv1Xq99UXADz0+F2f\n5cgls6Eh1+mGKDzw4hNtOYov1RgcIA/UPexYrLNlBakQMEZtv/BuWj1a7Lut\nOpaIGMZjJNfCpYFzR91JqlmqygLgb5JasCRByLKACpHbJeb5BjZTTr50mql6\n4Ux9fqM9W8Tl+kAiG3KduX1URmeYxFZfR2v2P6T4r+fCcc287NmWsYRFaAe2\nskFa9B+gmJaNnyFYQ2uK4XLF8W+T/DalkGuCuSf2wKanKl5AEY9rgcNMR5ox\nYCxML4um9sOu5b0FUNFgGc853K2+1eOgk9Ec8E+lV/SaFZp6c6v5/tO4SRFm\nzpJM\r\n=Jc5h\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQChgpfYBM/Wrl3NG+geaXO2AgJ0vw/Uiyz3MCkBm2PB5wIhAL7y8smntIl9x7dmtCq0hUkX77BqwnLa6LI5s9Ly1QVj"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.81_1587007322320_0.05922456652553976"},"_hasShrinkwrap":false},"0.12.79-beta.4":{"name":"teambition-sdk","version":"0.12.79-beta.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.79-beta.4","_nodeVersion":"10.19.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-NOAYIN+/DxPmZUkbHoX1OEuCJuw4RXOGJNJJU8Fa9aVpZPEa70eJObR9YoOMlLEAyXs1+VN3A4yqP7js+aTR6Q==","shasum":"88789e94fdddc2352f3c8ec9351899de5cb6882f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.79-beta.4.tgz","fileCount":494,"unpackedSize":1029422,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJel/0oCRA9TVsSAnZWagAA9joP/3RX3BMUJSxluVsuWfMr\naxqP2iKtRvOFthjSNWOlVGa+BEpxIMeFPkeUzje0eajNOBl5tx/Ces3NJaF0\n3PqrVoWmzAIKrVNfld0p6AFAx66Z/SU7+0gyHhaY0cy6c45Zsy/yqUaXiHYe\nDwsCcxswaNc/FN6g+V90y0KmkcM5mbh7WH4MYW/sKiTiVdBEsykMP3cb/2qc\n1+J08E0Ofq158o3wseldFR8DJFmt/kH4K0g8KKuy4uMg8hnhG9ELMaHhgYwQ\nJPME4gGoQjFjuR4xjbPRv6Hywy96vYFeLlMOvklkDBzwWRfwCm2VDSXt5Q7i\nR9NNZty2iksBj5AB4b680hl0GiVW6fIY4jGoASQcsMOsIMlw2Dc9+3N4gI+1\nCWBjxc5kZrasBQRjGUWLr/QeypdqmCOVOgklXtwIC964kFrLn9cqpydedFAN\n1IrJq2qfUTMFOEZ1+P2f7ORu08h2zY4nea2GH0Zm04y/hPs3uwosF0VQhgZs\nM1cu6JSX+ZbxcWWoKizDBvmjFyzO7NSsiFCzkqhvrPOOF8Y7Juj6Eyk6FWZN\nCNOJUbOSkAXqt/hnMYApZjlzOxovnIyNklLzeLpRlBux0E1cFSq7OuQ1YEU8\nPWO0Sg3axXHkdwb1LfF6w5HngEFSUr5dYtOeZes9WeVE3gl3Zhe90EBmirc5\n6oeq\r\n=7/Uz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEYX96RZ6PFtLp+mPXTW2bcT2SfzdrZTUrREIP8+Dfp1AiAEWI5uFfDG9rmXzAvKRaFKT4mjs1frE+b4cNVPwC1iJg=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.79-beta.4_1587019048254_0.7911828342156335"},"_hasShrinkwrap":false},"0.12.82":{"name":"teambition-sdk","version":"0.12.82","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.82","_nodeVersion":"10.19.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-62rUms6vGXr6b9JJY8avhni8rJ6aOcRkE1aw+DMMHB8tqDXqbcGIyO1+grHHb0Fs2gjpLDWSOnorTJcQ+OsCLw==","shasum":"6fa9122177637344797d95b387a1dc0edd48611d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.82.tgz","fileCount":494,"unpackedSize":1029415,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJemSHvCRA9TVsSAnZWagAAnAIP/3/1/7IGXGOLWSTC3GYF\n+aR98yEsIr2uI6b75wMOho8FfmUaSrXahesE+Fa+qisVJJREsLka19iYzzuF\nzFgf7PIA4wPPKXUzCcszpAXVpraH7vWYurtPOedfiswfWE7E8HhqxFcNV2ay\niQgMpfBElj7WX6UtOQuKy1uWzLQMlhnpuB8PBPv5dEDM8Bz6heP5HXp6J6+7\nJUGQMAGW560NUTKnvaplb645HNtS4v2noxK7+GlblKTFagotH/RLF6QIYWor\nDYvEkjWSBU1lqmj69C3oHOtkMGqBItqNbaK1j+tq/XWwt88G9ArIYQYhS4Uh\n8WMopp2cmWbcnDl1qeP/AVYHQCmQYJsZ+892IUkSBBleA0OjtwRo/AUQpLk/\nesUnJ6AuQgnji3+tpABJ8qFp3Eq2WcgrXu0iV1uKy2lKU8yLMZVXOKCyFf+3\nn035NM2AbetoZu50ZKWcnzkHiL0e42Hh7fU3HjvIZvgnAE3V3abbdki5736t\nRohq/IxEcqBACgMp5uRXrlVYFZ2y1JALAn1dx3T3uCJkR375L/lGZu4se/Il\nkv7q/mjhcxj3vdbOpiLUcZKlV0rymLKqU9Spc5qFArn07sywrHuHzKZ9F1iZ\ntcsEWfzyxXdrbQkp/FQYd4lYNgKvtjxz/50rcPJtJlOqGaQ3jF7h6RjzJCcd\nGfTK\r\n=9rrS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHdRm/0G7rHIQSSdj3sRECNSvkxtOsCUXmMHtA18Z8V8AiEA/ePWrZ6l/0esF/JR2NhGAr20vYL+iAxtW9aJlg5vi+s="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.82_1587093998904_0.8255824722696199"},"_hasShrinkwrap":false},"0.12.83-alpha.0-customportal":{"name":"teambition-sdk","version":"0.12.83-alpha.0-customportal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.83-alpha.0-customportal","_nodeVersion":"10.19.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-gQbHht7VaZywPVQaMTvBtmtuQG9xOMSVP0qJuBYQw2/mHGNPSGvPrPjT+nsgjvNEp2eYjXk5uWlmAEshbHqJ2A==","shasum":"f68c6798fc837d3a292a089134362252299420e6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.83-alpha.0-customportal.tgz","fileCount":494,"unpackedSize":1029799,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJemSLgCRA9TVsSAnZWagAAnqYP/Rj2FtVQJNM9DfHVfQGm\nJ1HROCwZVfrgwMgNhSFx10v8DIFxSFCKsII4yafOxCS+momVtwvtrFDIH0ef\n4+KfOjuUQkv1CChGX7ehwEi3FTqpWE1XtHgRI+Y7RfN0lGsvA9xQm0+kWIZN\ngWMrp6dIdvVS2SVqmwTPUO2MFlmWxL7HrYCm7rhZP0t+w9+RGVzIpdb8V9hP\nU7fgMu+VdewwjK1SwSaKWe6Bbt2Fi4TBWJifmE2lSzajIK0Yalk05nMRsaLB\nL0qqnJMMytB+0kfd0NZjbhKLmlTb9Cpvh+MxDE0rymfwbnxb11ahJ7GasMn/\n55NM7OUdV5WmzcTFMIepd6T3fv2oQc0oUkM5DrXoPrmCX16HMJEmcdxNoCbO\n0+WuYZ639ytWTmpHQPcbb6tLbNvoCZ9rxBJsILwNbTV0s6A+98RowJPBrGGb\nyMO/mOsHrLe85T1w8HMo5q8k37F6ZV5GKhmvWk/hxbv/4+vOJYfKbiXKXZOA\npXkrLGMobcZ+H09sj/e4S47QkAt3zp+VCplh2Wcmb1K07jNjEc+jKhbV57Tx\nrN06YMU//LOrmJM0bHtwhUhCPnVrZ53Py+fS1VTwHvKYrXIf1wlJP2NG4+X6\nWMXX5PwwC61Gk7tVl0aQNj3j7wHfUjEvV3AoMREZLTvQ0DBpgme5H4k6B5UZ\nT1pk\r\n=fNz+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCbCgaU583Vdp0vGZMF5LSdFR81tMBN8/MQyHqyeYFQ4wIga50XNhDt5gorRJ3Cco82Ixl4swD6JmR63SZm+UFF5Pc="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.83-alpha.0-customportal_1587094240087_0.5087817404260289"},"_hasShrinkwrap":false},"0.12.80-alpha.4-taskurge":{"name":"teambition-sdk","version":"0.12.80-alpha.4-taskurge","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.80-alpha.4-taskurge","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-BuQYGhb1d7xPnsDsbf04qCmS/14zuhHZCva4goAlCttiFxtdn4KxX0ln4VTnqa8WnUs0m8A4+OleXzQd1/ryYQ==","shasum":"a317e5450557a8065bbe95b40985363c58702906","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.80-alpha.4-taskurge.tgz","fileCount":494,"unpackedSize":1021271,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJemUODCRA9TVsSAnZWagAAO1UP+wQ+c5B5vHJaJuf9D1Bc\nOg3Hv7lm0q1oKQCzVs/U0eFIA8ThkLEgOqzrscdANiMPdx2fmBTOAg2MNw3U\niECi5N1YoaR4Emf9I3C0gXGHoMF38UjRbkoTO34cRmEAi2Ivk1TPhIH0DWDS\n0rjfUdKmHBbrruLzy3a/FgkRtG/1vaJVy6Ags3ntse5m+kD1uLAVQQlSMrdS\nb83Fl9F5HmLOquY5T/ksIlS0GQ5HSKWRe7p894zkAHO5KSuNi/SAteIRUcfc\nU2dPNnOBOM0jXKG+A1dd67ey6SZ7HP9mFm48qG1UUBfPfO88AnMz2Av2dgaW\nYBZbCx/Nsg1iinVXcfMfa6+DY3CU9NuQyUbAiYQIRPEajvPX5J5JzVcmKaZ1\nIgqd979uzjU3mUFA+V4ndkqX4bFVMH620gF6J8r3YpKZxgJ7fF9nShZyXHzc\n8KOI6MrYRRONQ9GFlP3YHLrveOx+i4k1WnGBTw2lvPNVoQoMjIRZB3kGT0Ct\nm8uBWIKrh25llaLbijo3N/0ZOiM2e5QMKOkGJ6qIoPK6WbScx5YwrCduKvsQ\nogGjps2imYtaOD7FnhtGTwUqGHPnzEzuFrjzX4OMrkU72/lwBvK1yIQvo6jg\nUjTKdnD57Ar2wpLeVY8RZQ1iOVPR2fFJChrfoUoEDCg0oXQLB3SF0I49GeBQ\nIBAw\r\n=vUCd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFu3CgxFmuqo5HSJFp4Syw1bUlC/rcbK5B4bU03JGvbNAiEAioWiqX6x2gUSA58xOP6gQHmUd4hFmRWe0AeJhhQTtsE="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.80-alpha.4-taskurge_1587102594588_0.9050903666562773"},"_hasShrinkwrap":false},"0.12.83-alpha.0-taskurge":{"name":"teambition-sdk","version":"0.12.83-alpha.0-taskurge","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.83-alpha.0-taskurge","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-lLBNPnKIVI15SY12u6IqIvn2Km3FXN4J3WSUDoEEtIEy6GWCOZNYXWm+ZTKA2ZsZxu+Z1vxpMNx+FrXyTVRwGA==","shasum":"751b8673d3ac1df4898d5b5fb823c6a7df820cc9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.83-alpha.0-taskurge.tgz","fileCount":494,"unpackedSize":1030184,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJenQ+0CRA9TVsSAnZWagAAAuIQAJF9eHn1CZvSWMDOJ/dO\nLGQCn6W0w8m1wSpnJ8nsFa3C/2io3dOjMPg4uaRP3+DaCjvKAdkp0rrfiVpK\nQ3d6K6s4dR6/7flgcFtxQqLgooW8rM5e8habT10BuI/12OIOkL7m1m9jR/99\nsYPEA9AI6aelZ5O3dI5TmRjGoNQTIVlMfaEkLy3wYkFPQYI7G/uqRtST6QCV\nqf/tWfwnTNn+iv9QeTlQIhQFrlKfTFXaI3Wl/bgMghNfkJoxMowEj95qI/ym\ngSqlgq46FD2qGGNXgc3C9D3FPvYghYZEaEIqaq8uwLB4WcfXYwZyIFVYTfsM\nt0tQmT+RYSxN2/jmRRb1PMbaS3w1HZNuFBiBgmn/LBvXuiN/AbASUXPREFmP\n+n5Ibe4oVUaIAl0i9orWKv9AvafVEKF56hTTlPLuUhrkkKldq03sKBWbKna4\ntrS3haDtRFIWz346Xdp/h9EG6o2nx7BS1GHztQKhq5omqNmaFcNS2KlwT7YH\ndJk71H2C7btRKU1ptK2binuqmDq7BYiLbtbiBWxF8tOziFHdIcrCqKxKv70A\nXW5qiQOI2OVZf9Jph/DTQ9hYadufZsDd7N5LZj3K3/iIzjMiDr2i2anzSDjl\nYAjbqR759LvLgeJQCfR2H68xDtjoocNxR8VwbuHjphIa5Kl9Q9LAaTifas8L\nXmKi\r\n=G3M0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAixwezDjvis9yl6mQxG3+omy8r77jFMA2UAz/YuR5rnAiEA8z6NkVdbh8fXm9DcgPkK7+Z87DVkWHhkkKjeKsYTLdc="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.83-alpha.0-taskurge_1587351476063_0.8527431885116219"},"_hasShrinkwrap":false},"0.12.84-alpha.0-tasktrace":{"name":"teambition-sdk","version":"0.12.84-alpha.0-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.0-tasktrace","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-mPFRGsmiPyasWluG109ozTjqDTToNpU9uGY2FmlfIRcwHvD/z70AEpo716f5gVJaiZSMXmTLB82jugKsw//XXw==","shasum":"5452c2311188d10eef6d759c2492d9aa5a377a48","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.0-tasktrace.tgz","fileCount":497,"unpackedSize":1032336,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJenp6UCRA9TVsSAnZWagAA2a4P/iDfvI8xp72aO1FwPCDp\nm2ZOr3ROusdeQG4n/QjJwPVwH0dUZ1X3I6gKV4gnKxO/H7hn4aY+erw3+xhH\naHBFD2uAXaYOUWZit4BIsdWvrXiZNHGaWyM4vqRT+jTvvCfstvzja5xm7qOc\nGYKElxQuMwerTYLt6DJBXpKpLPg8XXcFDeS66xv1OFpdN7PUbNI+40lwJK1M\nUBfKLsIBgs3F6+ZTe/Ab+TCXJfqemx7byuKHzmE0pmescLX4HE8kZNoymdnJ\noKSPqb2/pllzZpuoTFeMHPfr0cbHUG3hMocyJSrY+gaaMmCW3YFKBn+m3Ysg\nw84G6DVI0/TxI7elpbVcpW5TYQfBMhBtHDH01MJbeCjjz8KpmAspaZQ7U+cv\nP23t6nIRVDhe8oHokTT5WENgxeWD/50d5Ak/ivvxRY7KUC5+C5RQAsOmEzIT\n9yO9ZawufFvzeQQhW7fxbfuxP5E/QP9CrMtKauFD1tcqjyjSFvvQHfQ084Nj\nMuNC5e0Pa49HgwHTg0CxH5NZAFfH1W3EHXTtfZJyl9mWR8xc4pFdmWA9zAp0\nfzffNaGdTzstG50ZBulHuFhLhVmAIp6NL5lmAmkjHoZIyLmuKiqO5E+8KhNM\n29ypwAtOyKCjQ8E+GXBMFuK3aSv+1A9fazhyOKuAYIAfZW54GDiYMGK3b5Tc\n1BEF\r\n=qLQU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDvRbBbaigQwGKJwx/Jhr/mIGMhfi8lJKE1li0PhSV55AiEAxrQToX5H1D4JMnm9e+aqRIE3K6fWWkBjEJOutmk2FOs="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.0-tasktrace_1587453587666_0.3850607040495242"},"_hasShrinkwrap":false},"0.12.84-alpha.1-tasktrace":{"name":"teambition-sdk","version":"0.12.84-alpha.1-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.1-tasktrace","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-/iQSyfkNCS/Xf8KelbkbR7lagpfl39T9LluUuVEoBFJJmOEmPQZ9cARf5eSUehdOnb/54I48rGOVxoroYmg+eg==","shasum":"5417d072aba59914d25fbbf993456ec7b914bf6b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.1-tasktrace.tgz","fileCount":497,"unpackedSize":1032455,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJenqv5CRA9TVsSAnZWagAAISgP+gIDOZBr9I4EBo/47QA1\nkIx7N4yOn4kJKcS/qC13xkhtXqLPBOGR/2unxgVGC4fu6b3/jBeqlURtU2nM\nPNWD7VtKhWSzErCpNDJOSwnlOiCMePza49d+JMsw4ONADwwLOUjqdcwA2QkC\n07Hd0z/AejEj+IEOtfOqbMWpTxH9wS6X6YG0E6Zmj6IOINqgUyo1Weoyzgbq\nAcUfmGHXi3sr+cUJgDjniXeogRabLuF+2DzGOM/FdggHBj5uZuO/82jAUDhv\nEkWh0QZocV/wlk9Itnp326PPcdONK408wBxE4Mm53PZeNqOL//mRqOkjPnJJ\nfVnkBmQ21aB1+6oE6URFmmJZ510w7MdR7I/SCksa1eoP/B7NFU1cYJejWuHW\nejxLTEKHJuxa63WVTctRKuN6Mhv4tfFGRfdqMpgmbXYYyPfo3IWEX3dICRFb\nl4uHTTA+MeOayijCesTnMigxIDr9cklBqCHJJPliONqOTgynIY9QW7+TPp1h\nHLNj4xBzmmN/Hf4j9o+gjBRfd+qMVM1HagBJeNh1JY64Rj24houAS7+P3VmV\nfb/LCf1hKAmSYigOObBn6xo7uvqc8uNWP8gUNFcmWqBgHMZvTvH1sfO/YJkn\nkOXmwaJxoRVDJ0arkYsON6FtHxYN4qLInVsCENgbZ1moqKaN1KqioPy0FJ23\nZa8x\r\n=cvoz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGJ4ZjxrHmrM3D8PM+xc22gn4a8xySuMJKS2E/i072P7AiBKTDYDX8b8Y+sMg1y2C9Qq3PXlvA2+fwutx5NYc4oiQw=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.1-tasktrace_1587457016582_0.6764630320532126"},"_hasShrinkwrap":false},"0.12.84-alpha.2-tasktrace":{"name":"teambition-sdk","version":"0.12.84-alpha.2-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.2-tasktrace","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-FJjZEr4iK4+b5bBjEnKSiGWETYtOL/bN2y0rhSeI+GmXICXucfjAxeYg7M8YDdWfY6fO70KQEUcI17elS6xraw==","shasum":"f3667700207ef2dca00ab0bbb8340f654cd2da29","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.2-tasktrace.tgz","fileCount":497,"unpackedSize":1032752,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJenryqCRA9TVsSAnZWagAA8qcQAKPmG0G8IApzI6u44e79\n9aWci1Tu6EXEwkDpS51Y3h8R0Y6Rr/53EWyZ4oCELKDhIibxwEuOYpnqre3h\nxtIfZt+jhAwhm1G46PulCpCZlmTlz1U0YFmF2e7G0rNkNRH1yeOaO8k93Rwr\n3iWc2n2Jf1ceQweA9GmICpMUlGEsp9S6sg9zwEfhnBNfdK7r6hZ0UZ5f/4rY\n3Wj/V92i5w4naHEc+Bip01YDeOivZbcWdkRsTiXxe6MtF4do3ZobDHjmXDNW\nDZjavCtWo9BW09g8oFaLkD9+jEpgy3srIMLMZvx9PIoUPbEyotgrb6bYPsYP\nxJEnRYdnZykcDjDYUG54q6bBWPuBonhZb/zaIb5I9maDrwrM/U4K7zJPdOz2\nrG/V372h1rc/iel8jbMI8mJmPIqsidgabitXImI5RVCGu+gIPtVcvsR8yCYA\nXBgskAe6N9cRtxlVUzG1EICUdFsOqxzC6tdN/cZKTYOD9PPmKTEdRsMcYUQH\nZTQNqeDj2KWx2YUO1y9s8/p5itRGE8i+FCB84mmAVRHyVzJhW51RSk9d3v6R\ncLHNPVQUyErhsdlsohrKel1dB379fHkWGzOf4munKMIxfQUb2N0CazbbGx0u\nUX7FKri3HYCAHqQ4NcWhvcxsa/spRBDSGDC7QZWc/aT+RXXtA2kqsXkLr2bH\nKNpJ\r\n=DrxV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCyI6Rsobx4sh/853bkfY89nDaEGu08IhyI+K1xWWEyRgIgGdrUte89DghwVVck4SWzw8MTRufIh8rD57gAO6Nw0wo="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.2-tasktrace_1587461289638_0.10586777931889402"},"_hasShrinkwrap":false},"0.12.84-alpha.3-tasktrace":{"name":"teambition-sdk","version":"0.12.84-alpha.3-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.3-tasktrace","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-8+3Zoz7Mi6To5cEh6/4DO/CSlnCXxrLwngydkIg/vC6sAQj7yaC2+uh+WxkNDEzCUkIAhlvnVw49s3N/PE2AVA==","shasum":"470e1a73f26ea5d91ccce35134b18eaa536c4607","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.3-tasktrace.tgz","fileCount":497,"unpackedSize":1034036,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJensq+CRA9TVsSAnZWagAAdRIP/Rrlrxg4a7RdqXzFufQI\nXnx9ZxfpY8PiL1Qbsi97GTXokE7cTGxnoO0x3NIuqgJAc2KBJY1MGtkh1QST\n7Pq211wSWOCjHLGJwQh/2RBBvHMTBHvYYl5VleDMbRytMCG4V+h3Kq2JB8rz\nQKhdITE4T/kr0tGtyUknacAHCy9k5+Jb7XZytntEcSs21gYpeaD3r+qrUFMM\nwdfSHfqINMBMKnjsyAxQrkzJyMEJy3p4ewOrfcRtYoXbnqeaDULmDofmw7av\nt5/eXATf4DhDcghsuuRgW17IXT/O1T0Hh76BjXVNLsySd2V8sY0CDfw1MG4b\n4BVFu3KgfuXywu9rvnJgMIJbsXq56T+k2LP0WykfDt3EjMnyJcCooQXU5Ys4\nIWckaXQgXK2UrGTDVkwGkkA4Qf5iZbrZzHdKgPJmIk74J8s2mvcBD9y4Yn0i\nBv0IGIBG1QF5AFUwb5rRMlF8jcOAosLNuZiVkZhoYD/zi/2RZBUZLsYE3wTv\noGbg/IzBqGUoxePg4ecx3Z7BzA63AYWlT3wOx1ol1VJK87oCLB2R3ONiCN79\nMLy4nEI20EoTf45EOGmVD6PkH3nN0UYrCU/UrJ3FdOktkSIQsQKXSYnhK0I6\n8GAXYAowDeVi0jn4NLsSz0GM9hvpwuFSZGdcfe8WFA6TB07xkL+uhyEPYz92\nrSjL\r\n=mqJ4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC/58s4u7ssSYGco4u4smYUdwQ/YzeHA2f9hevuChGuEAIhAJITCzdlUMTE8C5pF0lmkLsIAJBOlhdRwJQAajRJsi4Z"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.3-tasktrace_1587464893792_0.7175012528604057"},"_hasShrinkwrap":false},"0.12.83-alpha.1-kanbanconfig":{"name":"teambition-sdk","version":"0.12.83-alpha.1-kanbanconfig","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.83-alpha.1-kanbanconfig","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-IbGWU8ZVa65r/ut/zVz8tNyf/eAbZJFEkGpmNXu0nZHQK6BQfGW6YqRdoYZ3kTT4ex1OR3RudjM4QOe7tOaObg==","shasum":"fa370b3eafe77c35f8c607d3e18f70a7bb48ad8a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.83-alpha.1-kanbanconfig.tgz","fileCount":494,"unpackedSize":1029552,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJenuwQCRA9TVsSAnZWagAAMfwQAJsgX4je3k+7XMe/30ep\nuZTCKGro0+/24/70yKzfhgyrB9MvRTyOW8JKMIrDMspNAIiarySzyPiMcMvR\n0frlHbZV2tu/sEDev3U5augfXFTngGmM+Ybzpz4VwsDUvUxhX3EF1r1UouNr\nA2H6V42zSMaDFQFW/IWLBdGda2z5uPFmVYPF6cQTDpHBj260m2tMsttRFnGU\nBsd1S1yE1aAYUOhJQ2B9ymQ/kWwj7lTW/i3CG05u1HVSxew48/GTI7G6qgk8\nOcNO+lQ8A3I03BM7bKg5sDnO1eKSAD/Ao3zdkVp7jRE6BhPRzfc5EaQmhJ7i\nY5eB31SyjGUAL7C+TtEXaSYTswV9YC3xnpDPiB4cQ2VQfrft7sqmkvkAk9gT\nrgVfj0/7yOXlNqgF5uyRPj6hDPjJehDSX0G2lF36a0gTmZNQcoflGRRrT2xz\no9r0lrz+cEYpbBpIfI9tQ6ittN5t2e/CYYPw5resVWxdG6el/rc7u8SCxFDo\nV9Jo6a94VqvBYrAY6WkZhVCiFaRAXlWb6ObAKEm9qRG0T/dxixU8GLsqJrJ0\nuNxb42Yw2ElTalq1PQ54dNDxHvF3ELitkdFyDx4BNeNc/n4USDJN4xB0A9wr\nSNOnRHLoQ17nOoxgBQYy47AS7RiKnG4p6CQ+255GRGEyzY/t4NxT9JByOTRR\nbnFo\r\n=T9h/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC6x5PYo9RUybJe/2bnHw806GC6aWmTmhpH02YxGHbYkAiBxZrROv8el1tHPhoRoX1MFGSYxislHDy0xtz8hdz2LYA=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.83-alpha.1-kanbanconfig_1587473420308_0.13312733182113434"},"_hasShrinkwrap":false},"0.12.83-beta.0-taskurge":{"name":"teambition-sdk","version":"0.12.83-beta.0-taskurge","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.83-beta.0-taskurge","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-538tcvMP4Do5uTqX4/KM8DvzPq/qex1n1NzZ0+YCIDK4pKKZMBYYdmCWb431V6+Qsjv45MoH66i2jo/G7G9hyw==","shasum":"59b8741e89bfae8c2179da092db06bdde2acc255","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.83-beta.0-taskurge.tgz","fileCount":494,"unpackedSize":1030183,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJen/09CRA9TVsSAnZWagAAbfwP/i6K364sEH3aCuoY54gP\nhvmzGJFop5dwzm4ls+SAXX24IeZnxd9xvd4o/wGToOa8YOzc9oQXuuNze+xx\nVdI+GVevdhtGujhwuzz8f5DGtbrPtuktVZng3A8diQsYyIvu1W1CTejRalEU\nusAErGvm523UOI7YOBZyYW/eatePcVRo8/k1RkKSeXfgufxCNQcOYpqYSQ8C\nTkg7Vpn09XUhLit3WqIY76ltzfi98FtlBRKJEJssZLkkYhvwQvx/tswg922J\niCZFKecV9/AuDOJyKtIULeZ2Ij6S3ETp+3f6iK1YAhLxdpbCH2ElDRYmtLIV\nvh2Dy/wRq69EDyAs24+v0HykEqaXEjr9O8SVxj/FTasvdjMfBC6jJPv7F1LQ\nxILN3dW72sKQrpWpYkCAeMv4dJPAd5NFBusPztdbmkUIKco6N8jCalgaFgad\n73FAUEWZ34paj0PD2ZhrN7GmSxKD2Eb7ce47SVB8p663bwbzEJSCEvCkhLZx\nYgGULIGFU9g4gAzQ3CcR/9xEM5yFwENNnTuXen6j0L0+V6Hs/ovhemf3Nzl4\nPtRYF0iZ/ivGZSkCFO8bBZrjR83PHcaRPWA18WNDnkdFiXEBM/TcD9Ir7mhE\nAS8KUtXrjs2YFYOWNLnsifv3a08zt/44u/HG7OnzpAKrRNaCle6OTCbxGn1K\n9EYB\r\n=R2Ib\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDs7ESKALL2SrrIcVD1bUsfDXscACZsyaNhrRMojzVItQIgCg+JI6+MEjnLqlN6MI7o1aiIRblGIGSFuq/QAotG7RU="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.83-beta.0-taskurge_1587543356169_0.19159923405203694"},"_hasShrinkwrap":false},"0.12.84-alpha.4-tasktrace":{"name":"teambition-sdk","version":"0.12.84-alpha.4-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.4-tasktrace","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-gH4sloNFoSKDj4tJ1qhPps1c90HyTmNb5XU0+pCJJFRxdIH68b6eI2CJfBesMs1xJkk9bA8RNh3JFdXcb7pcNw==","shasum":"8815876a9e3cb700187ddfcc0e261c8a0ac9683d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.4-tasktrace.tgz","fileCount":497,"unpackedSize":1034788,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeoT3hCRA9TVsSAnZWagAA1WwP/jJmbfrXvvtgO7J8gXeI\nanygXzf/3zFgQ+y54wDkfoDZzXQG05M7Hov73drSFJje93CxWDeWQwZug2Z3\nPmZ+OguYs/BuJMQPlyyVJbFg+v7Fv/Xu+uKipHoUCnCVhm6XTsolyeBKlAK8\nBKhiVutuGkuKmu3K1XpP8OC7ZfTiJ46tR421/KCkCsFywixrz6X5E1EPKOwx\nXqCt/g4/QilHqCe/0uEboTl7YfP+QDqZP6i7QgRNxzUsKdmbkltIYKYlzj0B\nGLDTBkAv48+6FuRn3QnCSji/xAqbH3FiqkYo1DgxXm8O3M0ILmYj51dHoaLm\n/doyYN+G/tyWR5etw/Uc5Ud3rcrR54HmbeXUXasn8qaMar/mfBMtSsEM/zhz\nvUtj/cmednvm9DmqN5PsxVDwaWrZ7cr/1YIF4SlzmpG1iV0WDQcpLXyWq335\nmKT87PuA2YIgmgY6kuZTBpsdYnea4mCN9MRM8efRht7WC2tpS7m3lHTS9hVg\nIvAFX3Hz/pksFKJ3EgsDgsfCSuaO6rqJm8/1+xaNeosOYfuNBbT3TXfDoDLC\ncP68w//0zkIOf/RQX0hfqFzbK4XEe+Eb55C3fqj5+2ovcMdU3v59nes95xt2\noeT8YLh9y7zBJ5ar1djEal2VySIMSYKmQKsndxEzbZ5ilZsgw9HiEBl3pmTc\n53zp\r\n=Cgi7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGpYN4f66OgQnCR0PjnJXO5tIw4Pta8ELlTJp2iG0FRTAiEAx5ZclNzHD7ffr0UO1osbt4hCnDhuTdzycRKMlry2FWk="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.4-tasktrace_1587625440405_0.8544687531281481"},"_hasShrinkwrap":false},"0.12.84-alpha.5-tasktrace":{"name":"teambition-sdk","version":"0.12.84-alpha.5-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.5-tasktrace","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-Q4Nx0wmKqo0gQBYXhnDtM7JnyXhAwLczgYWxkuD9IhL8HyqrZvES0I2AtmP1uDF+Qmw2q1iIl6PkUac4I6uUUA==","shasum":"4c9f1709ebaf8bbdae9d5c5cb674092317a970bd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.5-tasktrace.tgz","fileCount":497,"unpackedSize":1035174,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJepopGCRA9TVsSAnZWagAAxS4P/RhRwXDnmW41cOOcYGej\nb4oX8XvgIVEwTqFep3blmywNHB3rgwz+QgdcIpTif5YxN81uUAwgaoykoHQ8\nB2aVoQEu2GKRlpmrWL8FwR3rxWWAoJ2SxQyXjtpkyh5wZ43zQfBHlRXapZcu\nHOK+FDuEcOJVbHbK80M3VyhDH10Jzrio9vbKcSjbSq7T2uB+XCVetD+JVz5t\nfGfO0Nf+PzXsmchhacejXRlXfKWKXKMN6sM8iKER/DHK3fq3cZ8oR4ELb283\nEJEYLemb7nYS81RHAETGY2HhfDFW/mIK2hmHusRWf9L8yXo+khZh9FT7OcpX\nWyH46lVaI24/h9ih5EHs6dGFndLfiUUHRMthc9KfUgTZTOiqirUXR3N4tXve\nyjyuecM8uLGGBzixZPZF21lXCvN1W4/mDhYUn455d52VTHgCJgRH37oyg+4Q\nhm5dbZsEYRFx3SygTfBrnmDlHDYJjxheNXFtn6jbvAYfU5Lw8wFo5rMsxcXp\nxQb/bSwGwJNtCSqkp2wBaRE0y1iBgOQZJskXyMs+FYrj4SrqKT7dEUQ9Dfqy\ntQXvtEHR8FY2k+8I4JH1rjXn3nUz/vLt9w/btPuEyoWgCdqlsSfzIkoHyE97\nz2qG/U8gc6XlNBdXh9guLAt5N8N+2zuZiKfC5/gOZAll0lLJ46T2LV/0wNzg\nom80\r\n=TBmn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGkHR402h22HcOg/844xEtKBsxx+6PXWKWUrotliYBG+AiBPP6xJOpnVfyboJavn8LXlJtuy11nPt5dRTLmmAnQKWQ=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.5-tasktrace_1587972678373_0.4562356837873178"},"_hasShrinkwrap":false},"0.12.83-alpha.2-kanbanconfig":{"name":"teambition-sdk","version":"0.12.83-alpha.2-kanbanconfig","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.83-alpha.2-kanbanconfig","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-MXEy78GmMbs0sis/aHvXijbJWy6x6zILsDcRfJL8YSZi44AASgoaWkHKirHn33TdHZBnsYR2VrEYJMtY17dyxg==","shasum":"f305910eeed0b43f83bffd1bb695f10fb3c66c3e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.83-alpha.2-kanbanconfig.tgz","fileCount":494,"unpackedSize":1030304,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJepph/CRA9TVsSAnZWagAAmu4QAIDxbXsUvDeYRaRmO+0c\nLkBqydphqkErl2qjHyVWXZoqYU8BSp1qCfuc0DQYSy8neS3ZuIS5Td8R2ByA\npIKAkrvmDck81nr10r3ztiXExLOb8teHx1yZVKiTh890exRND+rrYsCP4BTp\nnx4+nMuodIoZq+jW+8BcU1+rZCn6p4yqCbs1MX/lOpBSLW97dsjDRlQNFInC\nky3dz4vYkhWI56RyUUQ2cYGz9Xg0PjOfAiQ98O5D2N8ttZfBV6823i+XMSBA\nrummyzrPbWXmRr8A2RD/6eJN1idyJBaqpDPbXtfU/VUpKp/Ju8+L0qDyszE9\nAMHzEFk193p5uNpQMwRaDGT1FDgdyPCqGqhDf05vt+QwgtovgdR+9QsTsy/p\nU4gjqSw3xNpHfPFLaGDpY9Iv9h9Vas/6NfxaUeQyDJ4NG+Nj7G013anghSCP\nWpIMAmvjTW0Wr1nz5+3IWvGlkNbJSALuphOaYVyZ5b7nmrIN9N1C6arRhDH4\nX8E8WBxI8k3JeRD8Eg2VvrLzFvP90qHro4hhZLS02ERHdn1mtY9RvNURdGiq\n2CMnNyooTo+xOtIaxwB3ks5KeoR+aotVH3CFia8G1flofbs8RLQkmuVQF1af\n4drBkG/LtV2rbZoZoGepSh5KR2VxKSdpyDXGeTXyfN5dMHGGm7/Hrfmv0kYK\njXyx\r\n=xGcK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDik3CoO6LsDBnGNYaiPndP15PVWXNIAr8J01anjAmcnwIhAKcxxPxlspR4JZP5AiErcOuU+xj6+DcuhnYs+/2+L/Ae"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.83-alpha.2-kanbanconfig_1587976318872_0.051390988325488385"},"_hasShrinkwrap":false},"0.12.83":{"name":"teambition-sdk","version":"0.12.83","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.83","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-h+nJZoEdKo9QR5owlZRZ+QQFgyNmTgF3qm6Ib9+vYnF1ps7iR2GWilqiQUqOYaJCGrbPMLO8vxQYAEztAwWNKQ==","shasum":"05fb9d58b191078dffe1d1b7e71cb6fca072ba77","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.83.tgz","fileCount":494,"unpackedSize":1030346,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeqWaACRA9TVsSAnZWagAA9OMQAInydzF1tx+uFSnj8MTu\nDIjQhj/eHWiWfo0WbVhwNd40VqE7wuHDN3CJbnFLt3kwki9vwLSVGajPOdqn\nTqhHtzl5a2yODRTm90d+WKBRlbay9Ib1QSIlz9dLL40SW61XBNY3BYADg7xz\n1JAcXVrASqAjOu0bG1kwxzRjW9JDMSIKKxn76SL3B8PQS9bP7mxEyaW2HouQ\nEJN7IktyECRywL6JxG+SyrfdymwK/RickQqBixESFd/TOPhVqE78hGkqZWbl\ndI5ZJL/Jdm9tKq9+zHQyiMUD5EMQop85fwA2pFLtew6BIfy81PEWSaWeFOKb\n/S3SlDiyFeZgu0gGgW2ULnekeG5mXPT6dxIyZ6VhqbcoVg0rVMh1ylkQ9wBl\nAAT9aUX0Bzbm+rU54Tj+zxpoPmJyWewu3kqY93W5vOiBKy9p7NY7Um2JqPYn\n9aBjy2GjFB8WZqOdivfeFvBhZh15vNMFjpTRC/38SbVuCvQXFh0NDYp/kQCh\nV76QlmU0PojMIUQ6pQngTfFEEiBtddFEV1znx0lIn82KD+aSCYuHU79k+WLN\nSYgOcEjLb3EM6rijJS+Msl7+56dOXkqTH6EJagE9wnxr3YyzvBLBCzEYx+55\n0ifAGjaTSuDD+BL9nptzNlLBNeEPZBaS7sYdm8+1/On3NDZvKwI5IF0Xj2xa\n1pRK\r\n=quOt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDTVDT8oc/BhNXnlYzY/zD3996C/Su0WRtIPxzqbZR3PQIgWf5VhixkUuB+xYkU2Tkv7vpO64lYUVXYT4wV+n/yfiY="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.83_1588160128255_0.6304336500110701"},"_hasShrinkwrap":false},"0.12.84-alpha.6-customportal":{"name":"teambition-sdk","version":"0.12.84-alpha.6-customportal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.6-customportal","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-Sxv93YcKxlthM6ruFGUZqeC6CwU/2Nk4pplwHpG1Pv1X25K+AJZS8WYPin+y3YlCDWMyvrPLZiBIVApzQuVzJg==","shasum":"1714cbfa74d086ebe3dd4b655c3bc1d8b8b04861","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.6-customportal.tgz","fileCount":494,"unpackedSize":1030730,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeqmWzCRA9TVsSAnZWagAA7FoQAKUox1fB4jtS/8xqPuYr\n5v8Cv9HnbvfkLh8A575JqTwtNk2Xly9lMn9atS86tUgc8XZT+wnyyPCqdJJA\nUBlPRlLckQrTJNxLZQ9SH8uQfrxb5KTJXyPtmGYpPjltErJ+aKRJFyvkiW4O\negFLIbe+dLvzx5whUmEhdB3y/oc64Pm4JycWPxJnQ8OmYNEoLZFutoOMtn/B\nAA9trV/PeItU0RhFeJzhXHqjpvQW2ksqy6Zh9O5JLjEqXQzLZ3NewZ7FIex2\n4+oYXMSZ3Dm/wY8TT4ltieSQXfb4TgUajCgV6i///HYeMmQaeXZNhSahvWsf\ny9G0+g2Ci05+1CtA6JSb/QWMsyOguXW3J5OIMVK6VbcqNAavLrZW29wLRMlc\nrSA6esvKaPprXq8BVACVQjajAA/wubJjJ/XxlfyDC6uO5zMxjBz3kQLZLhrT\nAnzGQyEGmVFRtaoC6oU0SxymK8M9R3STA50RUzseKpyr44sb+4Qp8DE8ywzM\n/yb/lah0FxJgg9QgrigwsyS1ZYpmaBD0t6FTb4xDHX6d4ncK87OHRiPFZvDi\nZSl/hOy+/gnrJZeRs/zvIeLe36K/LXStcsfG/vdwuhO3OkU7Cdqra+2PFRpx\nmwSBLLow9qkuMnL99kgTApv4Q+fdzJcKA/6u+WPa/b59wQja62Ba8QeI/phc\nC8I3\r\n=vmT5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBxzrAcgUK7hqZjUqe2jUnqS3cfVCj7g4eqQwXzTgK4RAiEA7JJxEHh7nlL4qREveeYtAJzEdq1J5jRR6CbKZPkm2Jk="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.6-customportal_1588225459079_0.8243287149867482"},"_hasShrinkwrap":false},"0.12.84-alpha.7-tasktrace":{"name":"teambition-sdk","version":"0.12.84-alpha.7-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.7-tasktrace","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-Hp812p2L+Q3Jj2buXsSSPNGliWVL1CLNsG1CplcMBltMsbF05XIAWP3vF2OhIoRTCbSQa+Y2OqfTTPZdXglwZw==","shasum":"a03ebf33cfb44dbb9373045c4bee5a571005c48d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.7-tasktrace.tgz","fileCount":497,"unpackedSize":1035353,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJes5qMCRA9TVsSAnZWagAAtkAP/imyCxs6j+ZhlVRcHcu4\ndgNXSpuwIiqhza0/tJWautklMR0KAfRCRIL7W1BRKk6M39moweVGzMkO+wh2\n/JCcUump6bIv7zI40HR54Qta9AUugnpjqGgUZR+bnfcQaKnoGsd1QovM9Qdn\nvvTtDlAaQ+GEaqF8XEL4HFLDs/HakYvvkNN9JSTfMbsc6vDLll2D7GtfUtBt\nlVuNYTCM3VTTQC7Zyw9TGr9Ydusb1eODk7+aycHHvYlHATuN1VL/IpI/afuD\n5sezKGnmiIfs2BRf4AOkV3bfQ7IfxlMAbQ4n0+jHmwkF3myxtZIHynQY9ulw\nV00Y8mLU0CgmlYi926Iwj+aTFrUhCEqQvy2OQEIyU7H8jjidVW8dCYgImzXd\nZ1Voym3dP54QENKJyurBQqKFe3CwZ7ymtdZyknjo29eBvLxDoNx3V0U9sac8\n3ahU+3h5ZkEk4ZHfC3HtPmSnrJX3mQ8PFx+QrV618jBZVgUJ6XPUJHfl4r8p\nnaASdRcw9iHX4L41ZapERyKPQGPaI8AC/vO2bpHQ0abWEZQcqyoGDiAQW4yR\nhiVXTYfblk3+4PuGiPXctioeC1CKNcgW9Yp3I1jRVJrwzLPco2cgXbeg3qh2\nyJ0zI6eMO5oSq+ACx5AYIHvdfWEpyFPnW/T9RVLdnGuzGkpm0c/IkrgjZO8H\nOv7t\r\n=c7Tv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC0YHj+um0jAwHMiiNXK6qSyBC2Xh3IQCTkFpMwa89trQIgW30QzhaHFFVr+EhzsiTWBa3lqIGGApYhxzvSAlATZSs="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.7-tasktrace_1588828812167_0.3164107105528844"},"_hasShrinkwrap":false},"0.12.84-alpha.8-tasktrace":{"name":"teambition-sdk","version":"0.12.84-alpha.8-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.8-tasktrace","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-hIOHDPk54NQnHsmSDZz0Fv3e0HN5LODSSppmspq+COuhTP7k9ZC6p8S7LD5ZMyygsAjXrdv20uO2eWR3x5L6bw==","shasum":"b2e58b23bd38d2ab157d61eedb460cd47f489cbd","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.8-tasktrace.tgz","fileCount":497,"unpackedSize":1035679,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetiysCRA9TVsSAnZWagAAsNYP/Amb/oDbNbG96r7Z+arL\n0vm6ZFPGtpClVnUzuBNG1PtQD2TlYGSRoD0Z6IBMpXAFoCypCuvewk4yzEu+\nly6GEzClV+UE4fbi/JxMG6AdUr8zvM685spC6EVl8R1E09k6ekCZnMI/kPv0\nUJ1JCW9wVGvXlXx1TXBZ8W5eKAE8jUGA8uAnIPFJ77gqpr4ZjvxuE4MQxrDT\ngiPRSJL+xm/h1JBEKyYPhDmXiFEIGdkid2qDqYhrvnEtz4K2LlqyVA7iiBc2\nrmryRfasOFK7gkWH6u/OPcP1xPtQOER9j9dxcJm6r31t5PA+A/eOJ6q+4K65\ngCOuNU/5d5y0tRwdSStq4/9A51IhVHc2sV7qtTHUk0R86O+CD8iBK4+JZ3RY\nuQkcxasrWgii8MiLbrIXdbRlsZ4dIMLmOLK7EPQ1KR46p3A2r7bhROkhBNOZ\n2nH7uxP6SF70z0IQzfnlsxK7sGsKBr7PQONKa0LTtfFurqhKsPEulR/0ogn5\nu1MhxVNWBItmgntQAocDzUPGqARDQhEvwSdcZhrG8+IBdGupek1xwK3ddLdi\nAbZtLSJKcxPMvISXO4EYUWL+roPBLlmwY7gALFp9Zn0r8RxUCHCeNALBBbCa\n7ZDUYXId2Xf+hK1IZpWvzWesC4cj2JowZH1R6nYXGuOMUUsHPTGPZxe0/DRt\nxDIV\r\n=shm4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHt5KhVtpBdilLbJNNjZorBeK5nzrLAJVxyzTu+B4aK6AiBd75bG6DbMleLuJZpLncjjwqPFp6+Yh2peCEC3ZrQBqw=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.8-tasktrace_1588997291502_0.7997334052944169"},"_hasShrinkwrap":false},"0.12.84-alpha.9-tasktrace":{"name":"teambition-sdk","version":"0.12.84-alpha.9-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.9-tasktrace","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-FJZkamOAFYROUJj6AGixyDl34Yhdygy+AU7ThZUGAsJJlq1TgSvXiKNyX5FGfaLt7/uOBPzqT/qc0jSqLqsllw==","shasum":"5e9213a23992540827606b37d1a8aebbfaf57461","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.9-tasktrace.tgz","fileCount":497,"unpackedSize":1036230,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetkSBCRA9TVsSAnZWagAADycP/RgDsV6JEWAuWsxlgamf\n/VVmABeMGXTXvll8+9XLq+EZBeysw1dforLABJ3Hrq9o7cMew8dMyL7YC/Rs\n58yXVet+5m6VheDhIbgv8H2h9kna8envsCzXcRAnciY/4ZmBpNzl5Pclo9hy\ndqrBcFetyCBK+iInWEXf7lGgAjdl0YND/uhJ/PyCYunEDpZ6SNkpB2cgmVDv\n5IJxwVYfON6NCvFr82wJPWFpQHftC23zUayt9XNxevqokvVSIaOptAI3Cx6J\n3aEkwlPsoYCN87rF45k3mJ9JeZZ2x4HmJMjbJEzmBcC849h97QLIExXbaWYK\npBj2kNyP3pEPn37NZYomKG5L0z4dI4EortKEE3dKQL3+g3gGKSXZ1zzhl/JZ\njYbl2Gb6RY/ipLm+CZtgbxMc3JYQGbiHaHKCZ7pdqi2MFsyCQmEXI+RB+pU6\nuF0627OJl4xFACdjcqeMmj7gqVDMQS5tGgUyUM9eytEj0MjtKNhyjqsiI8hZ\nbF4RM4sv5ly0tIJBF2dq7V1QJ+8XqTWUO9tlduwce0uc8n6o7qJZ/WnbJSwJ\nFSpxlr1LCBHB04HchNAYiAcz8Dz6np1V0myvHSg22bqKbqm3ZqM97MS6S2AN\nUFrkrs4VloeLpEualI8IoKgLhSDmp6BIYBYRcyQr88Mo//Pz+G1GYn5OgnxW\n2PR2\r\n=LZy0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDCqbOao3eiEe7GQ4ag6qaJQzghvJaaewG+vbTWVd1tsQIgDMomYnCXIcxiSZEmunmb0V5eu+ADBGjH2D4NtZ1FNSk="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.9-tasktrace_1589003392982_0.6101714406587453"},"_hasShrinkwrap":false},"0.12.84-alpha.10-tasktrace":{"name":"teambition-sdk","version":"0.12.84-alpha.10-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.10-tasktrace","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-8H66FTEC9ddP2jRXGi81Yz8Xbek0p0J5Tv6lwbFTGqChPISjBpSQdN02r26gzJW7nmTS/CTaxCEnXpjEDZTyXw==","shasum":"f0a1e1289c995b60ba6e0c3a80689e35a04ef072","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.10-tasktrace.tgz","fileCount":497,"unpackedSize":1036120,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetkeDCRA9TVsSAnZWagAAuYcQAJCmnOMASQ9l+cYRIRPh\nkYrZtQt1yBYt2VmqYc6n3bHtwbB4OHpj2nks4r/480SWqIulejoYihiCD684\nyeAG4515HXyOyJ8sFc097K45NPS3WBLNhRIsS2JbB4nAZeyoABrGaLl/zxrJ\ndK3H56FdNIjJIp1CLJ8wujPwHH2RqDgOoPfAiKcLDfbH8nSQyLF+DuHVpHU9\nuUaRysNlGeTg8wisBtm14Mrs+vbCxToJA0cswmKMcGcMmtnfy5ysSqCz5Fj7\n/AKyV/UUJYTk6L2QURa3ikkuYi8DzGz25XXltoPoJkAwzBoUnrI1aEr9tVME\nddMWLJCQhQZMcIAuxq2KCGqqErnXF5j1NnJ7rSpG96CG5I5ue3UoT6oOwdiK\n3Cny+wGyKvv0Qj7wd3e4DaKJaGBMFpGdeZScKBQiD/aDqgWNSX2N9pXwaZbo\nBRUys0Jq3JnDt7dJysq6O9nKDcJn0L04oUV6yF1FTogLkKbYBn2yu4QGvcEB\nrpEiQveZzJFIirYiD52K33gviSnfRud5UOL8VKIe0mH4zkiHPTDIy/nijRUj\nLePxMQMNqJn0G8uGOsLECLMLj4J5NmP8lChsprDMktZM+pwFJizt2SDmUr8t\nS6WrfMMr0k5+JigDproKILLFqnN8BEh7ClRgpYzhbsIy3sXPQqjHY9JAb8zS\nOHkl\r\n=iK0D\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDxXX7Ur3HIB8wKfGUgthgGgxomuli1VBJftmdYrffa0gIgeh79Ph05wQD8B8JrlX0KM0MNCgSiMA1ZmHa4IfNJRHM="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.10-tasktrace_1589004163373_0.8764363514285751"},"_hasShrinkwrap":false},"0.12.84-alpha.11-tasktrace":{"name":"teambition-sdk","version":"0.12.84-alpha.11-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.11-tasktrace","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-h8S+90xfimfcbvP+kbK67WhPQRETKDxTdGHEX4QqyEq1rE3SI4BQSRMLRRjINthoUcN6BV+Sfwp8kO5PF/xaIA==","shasum":"0f8240277e2409a0a6e74a63b05f5337dd3c8009","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.11-tasktrace.tgz","fileCount":497,"unpackedSize":1036311,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetlB1CRA9TVsSAnZWagAAUEoP/3j6rm5zGJyg9xc9dZCX\nZvpK1k/qMRzoJoYqbz9LIyLCNJO/LZsK5Cfda02kZgsgwgAwCaBsdCzv6BhE\nhG7TIAveabSpFoeVe2oOwfBqdg3e5wjAION4vvyr1KRj4gaUKSctZkbCTVcn\nM4wp6m239Zl2TvjS8MjhtGYHRC99gInX/2B/KigM/yi6fvM34Ayd1U5QNV5q\nCf9IlO9nVHMJp/QwiKxgmuupyVys/enNI+LSl59PLaJ0kT9DiUZaPeQBg32q\noU/qqrJfhu4muMX4fBLBTKPGOs5JcL/gX5tvNiHsbXSv22rU7Sxm3ag0Tf2C\ngMoPV4ZLxf8Qg0dpRIhcGq2C+oEGisBB7QWq2rbI02ljLBw6B3UeF3irdaiB\nMldThlNJNJSe2lN5lOo7k5Q73KKMpNwOU4C/qcBQeuHWP4YR8BrwJQ0Vl4zT\nzkad61OEwvoexcM+rCn9QPe+TZF3CKLIPSlqYteEMpNvqI3NuLySS1zPA7ak\nQZ/9v/8q4RjwImAZFQxC5ieCOZJ7fA0g8uxvXmrLZ+sdyqE+E4dMstz/C6Vm\nxRGc/mNVQqXS6HN/ArvOn+rr2g1HkQ3QBYoLsZY3Ytz6QaAWSEIxQydzqKcJ\nmiNUxhBvxg2COih96UJyaAdVf6FEmJlqmSvS93pEmn5M7o7eLnuNr0UJAm7n\nH6b6\r\n=nHqv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCqGZHdsxi6inkY+spqIndm7xKGVmgAPqGdS+X56hkdgAIhAO5UsdGZ1horB2YpQmtrjc+9VwsM60pP8aiqFF7SDZek"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.11-tasktrace_1589006453346_0.3010294984221338"},"_hasShrinkwrap":false},"0.12.84-alpha.12-tasktrace":{"name":"teambition-sdk","version":"0.12.84-alpha.12-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-alpha.12-tasktrace","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-l+3wOjXBkDIdcAdvwD0K/5P3u+Xdxi4/M9nZmjFXNbK9wgAjy7Xy/aVbYMFga+8DxEetGDqX/NrfY8AABHm6AA==","shasum":"4d4c1fea65617098145a20a9798b4b6296403652","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-alpha.12-tasktrace.tgz","fileCount":497,"unpackedSize":1036825,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetm4RCRA9TVsSAnZWagAA5fAQAI84lYmlk1s0F/6PG2JG\nSS1Fb0HqFwJvHpd7Ye10uCUgUZ0yU6/aaoBKvJKdIqvKlf8aPmWRC7b7cgc6\nfOEw7SqR2aRXGYNiqyck0JzY1K635iLvanDKJal1/UDmsZ1rZk1BqEXvZccf\nWz6K/xEHdkpDbTomcfKtEtCPRNxDU4cvpOZZLNsGiWHaiaXK7eMk48iJ91NJ\nLvr2SBjP7C0McV26kX9yOKUL7f395yatrq9Jr3qHkAMEaY5djL+rX/J4Y+kx\n/xWE+56Xo+Ru095/ZCEkCievXKLQjzDBX0wdr7GhfvSzztcWWX7L/VtosWai\n/BFxJMvLRtg5SFe2tPATDH5cvJlYiep02oPlMVcJvWw/d35xPnj2bbKDxjTw\n3FUvFxtJ86n5HJJ0rl36pQHe6KNYV6iT5PNQW/b7PCnv2DmOUaxRhQ/xhsQo\n+StV/8UldlnY8eOEsY3FkS++TTxa059cw1tw78mub4dMLhyAHI6HF/55G8UI\ntvbExcNjwwfW431QsPI6KZ3YAQwG9gbaBxyoC4Qqq57cabDkfKAwSqlz+0br\nezR8++WVMP3EOki0WZ3/odnYVCFJn4RxiAd+TE9sFhpOMHvW9SG5+FrsmYoS\nQ3jtCduSqyHWJDpOHvQTxLESZrreQy/99KYwaKO07zP941M7ForYNE9GaOsU\nCib3\r\n=zoFk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCzi+LPjsA2tWgYrLaL2/ruvNL5cRVcSeRCX4dxzwwgwQIgEJ+eWa0NI+8FVR8IMSOhR79ErHuUq9/por9i7TfFT2g="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-alpha.12-tasktrace_1589014032880_0.5790821910421822"},"_hasShrinkwrap":false},"0.12.84-beta.0-kanbanconfig":{"name":"teambition-sdk","version":"0.12.84-beta.0-kanbanconfig","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-beta.0-kanbanconfig","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-T55R0F8Ngqukok2Xq7SUQ/4o8m80sBr1qEqHVEgzUU7cVW+orfow1kGOUH3+VgO9X6ZSZUMsbdNDMws6k9Y6Uw==","shasum":"dce48be60d69fb66c3178af44cc6d4baa696261b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-beta.0-kanbanconfig.tgz","fileCount":494,"unpackedSize":1030482,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeu3FiCRA9TVsSAnZWagAAdogQAJYhoCLk2S9r5BKK7ZMR\npLY9V4SHaLKcKn9lOVx/uPpo/B/LQEQrRbjAayMVeh0CkgjVqpp0XRjGRskG\nGfY4xZBihykebTcnjs8jafuBWbTrTqbrlNsjmzCJFjkyWmuRivPkMKUGPmh6\nPHt93LdMEUti9QrN6OFbfGUzasEosxECamIiZaHsYSYAttC1OoIpkhFm/E2Y\n8fx5O0pKmpnk6AzmuSB6x4NbdzBIvoXMOUOajBhxfgYrY+7CRvCsRQh6Jr3i\n2v2nSNdt6L/IT5Lek5kJ79DciY/z1o0EshpPZFskFgCtgHoC0DHA2CUnFJ5A\nSj5Ga4V/O4znjdczcPuQOwi6f2Dip1h4B27y5wedRS19ij51+NrRF5COF/eq\nEkBboyi9bZ+26DBfQ0de4xeJpn8ORdNDgjIUxO5PuXedCRpu7f0b1rsZobBK\nigavobAFYt3JS8fEMCsvYxerA2ihZvSm7LHX4NGFa9xck2f4hqNg/6sK6v/7\nlTCPENRdQ6lBCyE5z9/9BX/yDtlcBiA6D3+qhEztofPpkWNqcg3jX7T5HOjp\nV9YBR9nXcTgDDY5BtLdTQKbxh0VSyHil3VJaEJyHlp/nnetUsES7OsiDHxzL\nHPYHiHHn6LIe2xC1Jk142xtnYH2ouow9ag/AQNQasnYgMtCYnf/BFORPkJL7\nfA90\r\n=JoGQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDZSDKUjAtVBf6NDHP5VwGCjFbaHzUHYnXQvr/eXuIIQgIgPP5G6Fr3Rv9ApVrfk/FmBYi9JxPH3q6yVC0A9LKZ4jc="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-beta.0-kanbanconfig_1589342561591_0.8279437352351882"},"_hasShrinkwrap":false},"0.12.84-beta.1-customportal":{"name":"teambition-sdk","version":"0.12.84-beta.1-customportal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-beta.1-customportal","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-l6iS2yATPLrDLhy8TWLuvNG9hqo1hc2p9StfJAfKr3MvdJ9pUbkBoUnFcUFMVwNxIC+0xtGlw/VIK3p32DwGcw==","shasum":"6302b1b05bcda8fc82fbb60bfdb68843394c60db","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-beta.1-customportal.tgz","fileCount":494,"unpackedSize":1030702,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeu60jCRA9TVsSAnZWagAALOYQAJQJHFBRyNbJjwUw0T0W\nnRK6qTDFclgBwiL1mSPbvTZDoSGpSjKt4gC42OA3RrGfq44F8HIBCEBRUs5X\n+XKWtNrTfxW8BTnXKolLZ0uBz8F1vMWIaE87vmQI5vdVTsyMqMzWWBbcxmdy\nCmkmKTBsCa84NkFmEhjqsrKfIRADbMG2Hq2YcaAZEyBAm1QYOOXs/LdQ4F93\nhv/DnnZ/NBne6UYbU92IAlwQwRamIkYnbyAyV8LOs8Fh2bTyafY57NAEn8K5\nbuiGJgKVLlYH0hwLmY6ml826WIkxaw/EWituIkTYpvPlKoAFZtV/usE8hF88\nBc7hTw/6udx8kXf8dTrLd9AhEmXTBUP6WHhvUrWRnozRZ6OUlPLgYWD3ay4x\nNyBqi5LWrO1C32jBpzrDDIeXOSIdgrmxFcPxhqm6R9RlKPgOT1n2hoNZhoWV\n4plWNxZ+IeU/uTKrad4+pMwDqlOzAJzgcOnk6UWPtrTQKrI1UTljnJPbw+I6\nLGUlma0VZxGRamXS64cg+8RK2GaBTTbsFk3HwjlWPiYGjMwpkiD4Ftj7iWGR\nOvfFUoHMS8v8KxNsffyPeA6tJy983osLJP3EZePltgDqDfbSPvhxrTvqDOpr\nZHRxEbfzNiFVB1FFgNcaCNfgjr65SaVqmhJ2dGBGUwWQZiQOFIpECjK7yD3V\nkCFQ\r\n=G+1a\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDBY7aXl6v8lVLQeEsfGDCrAEIv7/wfsFxUJz0DzErE+AIhAP3yQAn5SGyyse/ZmWNTP4HENoKGp1a5cVqAehp1xHQm"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-beta.1-customportal_1589357858949_0.14167531368476194"},"_hasShrinkwrap":false},"0.12.84-beta.2-tasktrace":{"name":"teambition-sdk","version":"0.12.84-beta.2-tasktrace","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.84-beta.2-tasktrace","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-NS7k4E/O5XjrHmrmEUiIKdEPHn7CpSD8flkw5vH8FJp0PCZQ1qCfQPGL+mVJXBztFaSk0RxC4VyNxc75yPy+aQ==","shasum":"f96fb3763522f4107f07099ed1ba9a5ff55f512c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84-beta.2-tasktrace.tgz","fileCount":497,"unpackedSize":1036939,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeu9dECRA9TVsSAnZWagAAriIP/2F83AGSiHsVBgLaYDwG\nJSTmXpCdpRAD3g7SEclgteN0enZKy/rvEqFpx5nBOrYhWSJhFDMhemAYp3I0\nG3ggsF+lrTUgkZVI03/Y2AHVbM5nbwuI10ASqpGXJW673rv+OrcN7M0J+eg8\nhoDiyAb9iDhpW0LoVIMNZZk2diB9ECmsvdmi9DldlrKtxt9m8m4zL91Ropve\nWiLkMYEmXUcwHGnZKTG9AC+AlxeGPyFwt/tNfbJyVtQ41vqI/mRM4cgP8Iu3\nX55g8JnK45zkhtlk5LZE5iSZKh3gRSOVLaKb5Zm1opnh11Y+h0agl0jig09Q\nCaAkj/acwZTQJepyO5PoEI6iVWk7OIk/GcyVnYEP1bAx67Meh1/L2zB3q1MC\ne+ksBPlDYqlaLdVBt4sqh5Ti9vqXAngOiHNBcrl943/W/LnY4rWF7tRGJYqQ\nzeoN8KtPtSEC7tAZj/5g7N4yNBw/KqQp8wM394xKjnpStLRogb1zhVhXhFOM\nuudte/bUKfS35RbQ6+BhvEdrexAJyi5OfVABHt3xe+oQAmjoos9vnaE6J64j\n43thDEwiKU1zAo5HBFN2B49q9knx5rJpfvNCp2ndilvTrYdrj9icSr24rWlx\nyDCy3DTDz55BRHWbKLjgbcnBJgfY/tjpnRG8dwge9TgIPuTFbE8XykQbh4/C\ndSZe\r\n=GV6h\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFa8b4N5e5u80mbRduEVhEyFllCa9LMHxUkWczvKYVXPAiEAnyoJcKh8K3IG1ST7+vwKYHIZeQI9UIzaClVAgYWcg40="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84-beta.2-tasktrace_1589368643716_0.20922403804529632"},"_hasShrinkwrap":false},"0.12.85-alpha.0-tasktraceobjecttype":{"name":"teambition-sdk","version":"0.12.85-alpha.0-tasktraceobjecttype","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.0-tasktraceobjecttype","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-c4sjahV7qdZzC0P3BcTvGWaiZ4uQW0MDS2M8QCsa+5WTI1YYidCDY6sS0CfUdFFMzFOjgJTBAy4gqiDJlSlBKw==","shasum":"9e600b8fbf65a89212cc2637d9467463e17bcbce","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.0-tasktraceobjecttype.tgz","fileCount":497,"unpackedSize":1037201,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJevP+oCRA9TVsSAnZWagAA+kYQAJZq2iczKcBtT6IfK6FM\nLYza/Mc/GUsrClUU8scV27rKif6mB7hHEsCE5BAF5O+ouwbaGsGeYvORcjQX\n52kZiK+fKaLONmQlS3XcpG+JiJh5oBQOYUsns6ndHzQ9nLXVTq/MBC+4DS8h\nA3V4Cj/SjRSVSCzvfKii4YZH6QVqoBOOA7nRBUjHgWEHPsxHNwkzfzxn4pIw\nDhhf1c1R1exqGOYyyieOh79L8gmhJbrNIIh2/sihc5Uugvk4hjP10LmJfKRe\n2PIJA8YPMySH+wuP1EMpeqiVCRKNTUyLXkdnvARhTlbWuvxTZS7xPgJH9jsN\nBGzuP8hsk29TL5lYnQ2V2K2zM0xMPDa85/70CClw/7wla6sqPn6U0nXn0nvS\nwvGLSCIwelKF5pqga8xUaugqAax/ycV+NCgrMysgWjxWB8mX2hYbiO34mAEu\nCRCqXrHAsqGHnJWg4WBJld6jnVGcb8oGbzNcrUHKL3PSweeaeglUNw+4BL44\n7ZBO+DXxMf87OkTSr6rJEFnjjYnmAa2/IffSz0TfvNaEpwmMdG29T5a5iUPA\nFJSbq6+at5V9vh+t/+JwkittOnGvWE/4gpMe1QkmZaKXxxkvfNc7X1MPZ94c\nFTzI0V+TRyuUGdwdVzDWf7srJwb523PBxv5+gk+a9/v5vRGBb7WKEY/wAIrv\nTkn3\r\n=hRxj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFsMDxyveCWOQZKTMmRDzXSeZuMOQTsZ2yX1UEXvpaynAiB1vYV5nnlkraAU7FpohAyn/p40Dxl9qGbeHpU0TG1AlQ=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.0-tasktraceobjecttype_1589444519635_0.1927255917353461"},"_hasShrinkwrap":false},"0.12.85-alpha.1-tasktraceobjecttype":{"name":"teambition-sdk","version":"0.12.85-alpha.1-tasktraceobjecttype","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.1-tasktraceobjecttype","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-4hYORQ5wpKq8A9QXhqoTmravBbS0DD2fbaQhU4KSPhJTvyRg+Gl/Wb5HCw9sKAm+136zzzxRpEewP/c7qoiA4w==","shasum":"040cee1a01f00511aeb8ce6c729a264dbae5633c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.1-tasktraceobjecttype.tgz","fileCount":497,"unpackedSize":1037221,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJevSwVCRA9TVsSAnZWagAA2MAP/3nz4xQ0EPQfv2IQYtDQ\npKurtS+yzGNwGJDy6k3/g0UjaOSaqeddIRsI4VG3RiJTDxqRmE58u9Pt6iIm\njj89QOduHbHeT/pYu4aSZL9sQJ7jX5nx/oPkFXO0BXBvCsexofpbUY79jd53\nkZaGJCdF37jdZ4aRAkgAv/HTte2TY4X64ovwIs+CxA4cuMJ6dCXu1aH5gNKu\nQhn5hBabmbry+NZS6TzjmMrKDa6kdT0FPtbpLFOPRGp8N2F2Qy15DSuBjMba\nrW5bFLhztUB1HOjR5/GiBfQESWcpC/VPhwFEzP4WitHf+irQ0aVkEw1a1klX\nd9mREm63G7PyfZHo3I1TurFrYECm6HV1ReZJZ1Ez3+dGk1cncDKmd50W4N+o\nEkMfVULHb68vyPnOaQgRdRDeoNfkI1N/u43WdeVbYQBCcZMOh87XqrR4l293\nnG9nv7cSuWI+GUJ+6JEf6Z84qeKi1vt8hV7p8OjHwEQOuCKj/ktDs7CvcNET\nzp0oVZz4aGYABRgBhgsLGSdyoSl8nqrayIYTGyoVQ8DZFSZ73m2TXS/vcK0L\n617kPkAtOnEuZ7qK7ISK4vw5LU0su9grdPEoYvlsJoZGKzAbW81hFryV87+R\nNPBMpjR/gysEi5F+oNdoBSaGHaFDy+tUzk9YYWy2MeGgY+CZ7PQnZYOk48dZ\nn21X\r\n=h9cY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC3nQuAQIHL45/P8OqG/K+HY0TJstyFzX9UiUfLYsvSiAiBgL7S4faaQ29luRn6dqVblJ27X9aLIVgAgB2UaLFKpsQ=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.1-tasktraceobjecttype_1589455893329_0.1494243602974481"},"_hasShrinkwrap":false},"0.12.85-alpha.2-workcal":{"name":"teambition-sdk","version":"0.12.85-alpha.2-workcal","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.2-workcal","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-VrGdz88B55b8q5RhUMeyYn+Oj+KAdqta89QOESgrJZIlELjs6Dt+K3PQzeMQN4dYSol8FW/FP2KbZJ2L6qCsbQ==","shasum":"875f23a5416833cfdfa5b061ddf5e2d0b1307f50","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.2-workcal.tgz","fileCount":497,"unpackedSize":1037079,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJewk+kCRA9TVsSAnZWagAARd0P/1xocMNYq3hcLvw4/lOc\neuFFcxKUQj5O46vFIWnvtpkzv0rdX4rdUSiNa35dcYeaB1egNuaFI2GDJRZ1\nmx8tw3OJTBtAlhTAdXC8aMJ6ZcQXjcs2LGzBUi8noMuGPTuQOhZtTfLP17Dg\n+S7LVnJ1Y6Trha04qF47HSuRj1VLZEsOh6asp+K0Ch1rXY1pLPjpkFTw03V6\nRd0eIG0coLYDy3A271oeyTMVozYeoiE3l88iBBrhCAbhA9FgxZx/K/C3GuI/\ntUpxe0JICqCAy5e8BbM2LB676df4hLb7hYFJtlCHDehdxNTwvakmmLZDOKb7\nNnb+nDAdF+Zls6wF2Da88FObcThaEmzqcjMfGC9Y/bjqAF6d46k38chE0SpH\n29W6LinsJUDmhkocWcmBNMaslAvHRfjn2iSrfMBZJV4v+5BTr5qW7ZQlTLeN\n7FcjA4KmwpL6+IxsmQPPy0XA+YiShYqrj8dhlpruAbojcqBbSIxMa22YodHv\n38ocFs0SY1bOPab718OCsjpQG8TqZcn7Xo2hSNv0V/d+to8sNTItqC56NT9J\nR4PtXPaGMifzsWGt1uYlqwkZEf46nx2Ww7foDjjEpPepQOt+C261fwb5ski5\n/k2CIRaG0uxDq0QEfWlXK+/hSIyTf3Kcp0Cjhbgygu8wgSLhlvweTzD9WNe6\ndY3F\r\n=h9Pq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBOyep+Q85ieNLhIzTaypWlO7J/NyPu3Aioq4JTHA/R9AiEAi5GtF7f2Vf2GpxSTKd0FJjOiPwOJ5NUomOWkFJ169W4="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.2-workcal_1589792675555_0.2740654540268703"},"_hasShrinkwrap":false},"0.12.85-alpha.3-tasktraceobjecttype":{"name":"teambition-sdk","version":"0.12.85-alpha.3-tasktraceobjecttype","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.3-tasktraceobjecttype","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-gW7cXcqu6C61KN1hxu5tz1BUFoc0Rf9h55XPm3AksBro45UKNLBLihQ5DELASsJsezbzLqrA32dhBEf9e6g+9g==","shasum":"848c2a09658b509bfffcfd6d5de770b9bb80d22a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.3-tasktraceobjecttype.tgz","fileCount":497,"unpackedSize":1037241,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJewsKECRA9TVsSAnZWagAAueAP/1HGYA/031SIf2eDYinc\nynODFZpttUUsYWG5FzClgQxWVQEm1PgLCD0LamMBHk9R7m2SXv89XArA+1Ue\nthYvFKzsMimilzwPH61tphc6/qm756rvisxxMHy9MSrhz6v8IeAmLCzvTvWN\n81ikE07eT9pUx8mInRug0KUzmvQSD1uAvXWDL2gSuc7QiD4O68JRLW2ekL/8\ndh+Hgv+0zyEjpGQZ7vdGW4Na8K0Yx0AX0IDW50IltIn3sgAG4qcPwQviAxrb\nz7OsYKztqDaeqQd0nUTlglc7xLtPOBFP7Zu2UHDLRzB1QKafQHDH9M78EFTs\n4kU0PW+1Xs/G/J34xgaGMhtWwVWPsDYNIAiO8dJ7zgOrHyK8lna0cuHCgC/A\nenxodCOW38tklWnYGIERmqR/D2GEhhDVAYX+NoDFyQTq2LNySjmnaDQWqS8h\nYggeUHD0jpJDeiCsIyIs+WN5MlSULblWkB0B09lhubJAwQlVBvwTW2gsXPPj\n9x2pEFLWA1JsK/sVa4s7AoX7nRUTsPyfe1JYDYeAnV0S7RKvqjIEO5/QQ5/2\nC7mBLENZ2b4y/uFIP4plUbCGBXoyry8O25QVRC6l2PlHhk5kZL7qdjcjmSyQ\niqyFj0cytwc7exYlTV7d0e8qDe5etMpoL4OTRpOlv9RIe32LLtApX02P8y5M\np1QM\r\n=3lAi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAhDb6UGqe4Uxw4RPNSOnHxH0UFDKSiA311yYGjUimcxAiBRYMAp2cPwa0FX1tHinH6PBt3yhOtPODqEtv84SMCD0g=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.3-tasktraceobjecttype_1589822084231_0.9330036506946635"},"_hasShrinkwrap":false},"0.12.85-alpha.4-tasktraceobjecttype":{"name":"teambition-sdk","version":"0.12.85-alpha.4-tasktraceobjecttype","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.4-tasktraceobjecttype","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-NbTlsaxCY2LzTFvJiBNUywzGlAsKBHnaBewLZzt+tSYTi89FradTyc4oAmgGRg7yWlb9TT2LRm7q8K5eOllxZw==","shasum":"d1c8597db2ca7e447351e2e81e9a6a5693d572c0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.4-tasktraceobjecttype.tgz","fileCount":497,"unpackedSize":1037679,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJew9KFCRA9TVsSAnZWagAAbekQAKUX6e9SvV33WVfuRL+C\n9e/eVAjxLvSH/AfpTonex/FBjvR9iMNXR6E9XDbXVvA2zpFvikaLpZHZibH1\nZ3b0TEv+BtXRkgbUVmpZLLHMa+hMImV5mrB7hmSCtGHWaZzxQahjdCho8pBG\nD/dbW1MGKZh6hkMkiHlWk9wcVGcXSawaxJVSmBxw6B5MQ1XLhziE/8wPsdSW\nI8T99MnSXGbKXHeWoXJt8zH6ySVYwUFKBExs7Yriam1Xhl9bdmiG2dhEaDM4\nXAzpECo713Rg9dK7rjlTvAAJ6UmLkjGX2TvhHtpROYYwzOpG9ilQgPjj52dF\nHnijBscDz+/wkj6O8o7xiXTqBuu7Jn1DhL3/YYei+mmkYDHuHeHrXJLN9U/w\nPmJfVMXvIaI7pI/0E9laQNj40Vi0gvB6UXHNINyJY///jhLcbMn5hTIq/6IY\nDfEjUOx92HrcaY06vSUt1yO86VskgcNgD35a2dhucx9wyZKQAaMXfFILceYa\nD8nk7SrOudHRKd6gxr441zLpCJRp1vgTHEv4olGhkenhIsEMnupSCZvwMVtm\n9zqYLW+cRnYIu1ZiPuqU8cYLCLAnF1sQ3jcIAi+44QUwz76Cbm7sqDlUTodE\nbdNufZYXgQaqKFDlWi8ZP3vlTVtiqr4OFC7CRkNnU3Dlak4VJ8Jl3/JCzuq7\ndkCr\r\n=UUWM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD1grvGdrWH6bpUMrtVYUIs+4t4dtQBHT9MZpMO3YpHkwIgDavN9LSWwFbR6DP36OClIW3bXnszjMNjPeouLLMnElo="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.4-tasktraceobjecttype_1589891716675_0.877606719650855"},"_hasShrinkwrap":false},"0.12.85-alpha.5-tasktraceobjecttype":{"name":"teambition-sdk","version":"0.12.85-alpha.5-tasktraceobjecttype","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.5-tasktraceobjecttype","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-KoJMoGrkMbGHgLcLzaiALy4p1EPURBZWqfw68vBJJJH60XZw9IwxNPrlSB3edm9tos1hLFT3lySyB2OTfrcluQ==","shasum":"4f5b0bad0e6771956019569ed58406ef1d4bfca1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.5-tasktraceobjecttype.tgz","fileCount":497,"unpackedSize":1037683,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJew/FUCRA9TVsSAnZWagAAXMwP/RgYhfePXzVmAMJg6B1B\nrsRcUvm/7IT1bs3HeTHiKlJAGfHd6o6/sk3hhRbZqOfAH8xSPYFhSaiyv1vE\n4nVYWTRm5O9JtVmHyX3gSuvbboFPtakEknWzH04+1A9uRRXDHEbZrXSXhrrs\n7jMgHzs+UsPLSE2PH3hgg1Dflq/ka2/RqISPmA2WyoXotxQVssKoeko/jjan\nAWtUWHS7Dr7voMpjRVQMr2E2HvrWLa2KwnXJ6/7C94s7D9oxTHtzto9/iHl8\ne6JqUWMason/SAr9DZ8vU/EktsvNvYeVOJOjXy1UmtXc1Z48R4z4BRCsGYcD\nU1R3iaOkvESEu0HciVaV2TuP7TOUDNHZqKG2DD6lWQZ6i6cv2CbRiM8BCXuT\nne3NJOaXsYWEE6a5EkxN1Tp2JjFSBWl9AWr+Oha8bMwv07q38ciqD0MvjoOy\nytj6xQ3YfRiuID86rYzJQbrdIaa2dg7DOGoIycuj68FAF/poBdp3U3KsDzJH\nCx4MStVK+APcy2g0aFdUQVbbFmaZle/50+b+S6NaMMBLlw+xSdvhTCiirY8x\nbbIm1Dc6jd8Z28MbwtQzgB/ZqT0WPhPv5rlKPAjcPBkjLFvyyRGyNDvuq4YJ\nTeuRfe+4MTQBjTKEAyMNTZk71kGz1io+7/XWHeHkEn/m8MYP7lEFpr3IOX6l\ngBQm\r\n=Dn54\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICTS+3KmDIw/pUYSZ/dbPGxl3pM93cj78pn1ftHvR/A8AiBVEHkPHqOLpYjwSLyzHzXKqdrXNnZHoKJt/xisdAlTuQ=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.5-tasktraceobjecttype_1589899604050_0.9038383977075188"},"_hasShrinkwrap":false},"0.12.85-alpha.6-taskrelations":{"name":"teambition-sdk","version":"0.12.85-alpha.6-taskrelations","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.6-taskrelations","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-myDDG9EvyW8x8T6OXk8VKNA6HFSC3URrp8+H7xqCYVLDkMxoXV1xYdKbRAQ6Hvx8TFiOmf37z77pYUyyaqM0ig==","shasum":"1da366897f2e04dce4cc3f85c5631bd96851dea4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.6-taskrelations.tgz","fileCount":497,"unpackedSize":1037437,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJexCthCRA9TVsSAnZWagAAt3EP/Rpaq1hTYqr3kHMnNj3q\nmpLxv6MkIwCDH1UtJNTXMeP7MGrOvBQbNtm0rwvNuF747L/Zz0ox7l98bCoo\nnCpHafGQbdHqdBhG6+DTyZH+ygJsyS7wkVjuIjbWlJHFwQ/mjy5ybQ6jvxuQ\np8otcLISdgiXTO+1Bf1BxGKDVSd5UyzaKMNRhiBN2iSeEfrkzrfdDObCXRDz\nFm9FZCXaDdLos+42GR9OyX4ivKIdOdr2W1QLRImXlL93rmch+q6t7NKHjGo8\nVN1uklP64dXE8P6GTHfsRte7ahUh1b+CNhJUJCOymPfIbiX6Ucp2pXGU/cMt\n9iKL7tdFxfeoHBUVw+9R7FqCRyGaINlUCP7dgRgrZds+kzcWXk2ru3ww+w0O\ntj7zBfcITMWoCA7fRr3lPVxn1pchWhRsSSrqdnhAyjML6rBMCZvxtHDpsjRu\nLRLXHhj8p9H8Ql5k03jXbaWA/K43plkzFB/5sIwqpU/JeDBsHZ0sOoTulH1R\nsYLGS10XFWTyWUUz53CsrLHWF9VSRmP6K3Eq50Bf2e7vEopwjb5JW9XqEna6\nImapJGElyMnd43rT24w3JAVeHUbftLFbrSUhCCkjTnyEfr7HurP7uV8caK9F\nrt+GJWVqH+oGB9N9l1pk38NHXaBUmNfZxJLUpksGqWwy8wnxvLqHi27nxKSx\nl7k0\r\n=imQw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCP6e8rywvV4dcvLqyx0WUk3t42tO/Dx6lS4dbVxqtfOwIgBQjixFa4lgqwjKKqPprHcqmuTJ7oJV26Qi140COMXqc="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.6-taskrelations_1589914464788_0.8322721377811941"},"_hasShrinkwrap":false},"0.12.85-alpha.7-taskrelations":{"name":"teambition-sdk","version":"0.12.85-alpha.7-taskrelations","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.7-taskrelations","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-2XrdJUIKWIRoZtl6JDqR6IXxcb//WB8Wt1LMZU5Q2e+n6aAO1Aa2EhlWWFnCxzJfVXzQUyE7y8iULbaQEI+btw==","shasum":"6d0464ec1910aabd3e53522ad36b370a028e82a4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.7-taskrelations.tgz","fileCount":497,"unpackedSize":1038002,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJexJlHCRA9TVsSAnZWagAArccP+QCIlEe4C0dlxQne1p2y\n4jBM6zN4AT9YG2WfwAT1JIA9CRveXx/304F1fD1IvLQBLl6qgIP7WMqej53x\nK9aXCCBj3gZOAw764tvVYlTBZlaTiWS0aOD72ReI3QVbu8LhEtlkSuNhaQJL\nulQ6R/nn4DGRnFoo0ELYdDMF3V2HnmydAJTJ3TLh4rNueMGLzx1OEQOS20J8\ngg7U7OZGpCjsNy38VIM+O5IBiR+yvKLPjS+hjK6KzUgaTlIkvSUmqsDDSoZ/\ntO7wIe4L5ks30pkU1zYVH0H+VCKBaXv3xI1OMLxWyN7aMOj9TuUxuLcxk0fN\nbwNnnuDVVgYQIV90SEx8U1z6B2W9mgrWxGhKOXwFkRU0p2zgUY0RhCtyzat3\nQ8aJ8Rteu2bHvVMlO4s553hTVGiEArjd0yVhQa0CXUm4KEQBE3pnNXmaf3CB\n5OMhGYppnvT8nHKmLS/JU3mvsTvNUQTjTM+aNp1SJGJ8bM6tYrph9tE2BESh\nBbqNthp5HGgMJfhHuUzcJLtLAE8rau9sCR8qm4GZjx+2tIHRoosz3M4MyVoI\n3vgdX0dKFmsulJrRFTxz0ZaZpMKoav8obYMz/c7cdNxAGUbjfYaZ755T4eUP\nRRoxQHR3WfM83fBIpg3l8vhTyEBVVI0ufs8fDwGXnitsK+oK/pFxI3TPZmu4\n+1Rw\r\n=v7/p\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDCQFxzFVt50K5Ic96st/7eQfBe8yy3jI6ZnCDo6UHngQIgPQZAbITrHEvfZ7jo8HERyiPPKrRJTDLcwJe979VUzYA="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.7-taskrelations_1589942599303_0.7162428770969207"},"_hasShrinkwrap":false},"0.12.85-alpha.8-taskrelations":{"name":"teambition-sdk","version":"0.12.85-alpha.8-taskrelations","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.8-taskrelations","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-lBPsCST1kx+cBT33ErYFzv8heOFjukxXNaS9P7HPJWTPBDf3TbjhcqOCE2mKhC51t5HpMnaoz6/tYctptydlQA==","shasum":"d04019a9cadd54f99754bf2cb368c7f9111e91d9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.8-taskrelations.tgz","fileCount":497,"unpackedSize":1038014,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJexNmaCRA9TVsSAnZWagAA5SYQAJKF/CB8TnYzofxz6c6S\nxDrQTIpDbQmf5VERwe1aoWOS4fSfJvwyZGPjHTjQIKYVY97jHqJAvqFR0NqG\nvsjaYGFTqkSV6Fb2FO08FLcfzFd2O4aQL0i6NNQYoKqVVp8sPmrmj+ZDmsFv\nnePB+5qEzXYJ7e2FoStIwjtsWJM4Bqi4y8IgGI1DGYon6IUgK+tM9oLcF38y\niljjkBps6ZeFBbD99B/2C3g/sNqjyvyQQA16GuYcsWk0NE1ROJoC05pffiYr\nZLoKunwmRSJ/6P5EyZvsXhO/Aby1clkpjpZBS4y0F+O0Vd9acesgXoQlxSHF\nPeo5MEjEJ7200HaCMJ0oXGk0tvHNg3uCFBcg1nbejEntUHctvNQ4rFR0CQeH\nKQpirGVp9SrHprfDOBSSIgwg1oRlX8v8lFNCqGaxs9fGf9aZ20dA4hjZK8eE\nmT41N9Mhl4rLdPjxPloFpMa2qhHrBo3U4GagB9+CetyInCpgyJAQBWzKKzVp\nXlkFNh36T4C7Cehx+MdRhEf/BDSdj1/lHQY0rReVaVEXOW9Mis8MfE2RP1ht\nqSibO+2pEZ11sq6Ol0NH3hn7bwFTajbZmvmd7muZIfyMJYzD266rQKDxweL+\n2xkH9Nqj1bM7xb45F2CeSp0vt3f8F42G6FjZvBMVcltxbEgNr1azsOFmj8c/\nudjv\r\n=V8di\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCbqK5rmFPKLI0KxRnRoZwo34vc5BaLvYYgB88Dl/5TWQIhANVNeiW78ZOp+y4Vy/+OFG7fLf1aef1qpgmKf3rLWNvb"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.8-taskrelations_1589959066191_0.8689948702006391"},"_hasShrinkwrap":false},"0.12.85-alpha.9-taskreminders":{"name":"teambition-sdk","version":"0.12.85-alpha.9-taskreminders","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.9-taskreminders","_nodeVersion":"10.16.3","_npmVersion":"6.13.1","dist":{"integrity":"sha512-6FwTPENF2npPU9PAbITeHUhib5x/xoWf14xnBKCf3JIa8yZBdasKeSsxLkUCXn2ikkHdqozh8y3Rma1+NMkuDQ==","shasum":"836218f5d85de2faaeff74acc5db1514fe62ec7a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.9-taskreminders.tgz","fileCount":512,"unpackedSize":1055710,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJex5+pCRA9TVsSAnZWagAAIooP/0YeM7A/y2/Tavi4+yq1\nvEIYTAhjBY9Tx92htXUOKrtWZH4tc2BcXtWS0twGuTDSTKyxJC0FEH7tMwLF\n6rVjL3TfHoccnoQT1HwBVocOzCNSSaPyPQhedQoSuqU8Z7Ahg6OR4qHrs3yE\nTKAWOuMZLKNoJxVOdkqzeQ/+njVLKmxD6WmGjFeRm/Hw4isp6Y72wgEGF3Mo\n/gO67pIiO2WahVeUxMSTSjVS2d9TnDKfQv0bFO41oQMRCilF+M10bp4ll/dC\n3V8OyZYjqTIUAkeJX8WSwxED5fvSq7LYDpoAMpFqPIjnTwAd73isYqn1nTQP\n51T6LcjLddofdEm/Kg9EVQBxDJPh3U75iJZRuQv9jxq7jfnHNUxa4RtioDnW\n5fDrlYThV7djMCeZ1rTywmmKsgxhcSLGG6B+EEdgJMKIZ1barKQ6PwQB7XOr\n8icLRmX3zry25V4k3B4L3IMyKpktg6gUSlcoC9RyhsuiI6D2MTuoNy4LRmTN\n9KEpOLfOdD6x3jhMRFSiN/vXAJr6sUD9qrLWMXPHtqEyKObxjEcE5J26/7Ci\n3iZI4rYUf9cCcypidshw2ZwRFswvcnRkgulS6D44jQc0pFiRXCegpbi8amtk\nRiHvjsh8Q60xDw/9cEHpbv7JOyRgRApwLoPYdaJQrARzOMg7/ox2q69y9j+h\nlyBK\r\n=gMoe\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBa4dAIYE6DF2sFsNOdwXI8r4lfo8PuqUN9dZ1jdVCAfAiA4kcZ9IC5FxHYnCTDacI7NS6u3G/rCDFzDoieBKN+iXw=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"jinchang","email":"chang@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.9-taskreminders_1590140841015_0.7926716935502565"},"_hasShrinkwrap":false},"0.12.85-alpha.10-taskrelations":{"name":"teambition-sdk","version":"0.12.85-alpha.10-taskrelations","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.10-taskrelations","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-QPTQeyflJt7+EsLp5i11/S7Mxyc4OFh/LyNDBHT62yArxYXEDoeBC9MRsQugqwSfAeBbJAkD8Di1X1sOErn6RA==","shasum":"fbb8ec3ee1d198726f50538469c006dae4abf31a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.10-taskrelations.tgz","fileCount":497,"unpackedSize":1038100,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezLEhCRA9TVsSAnZWagAAo2QP/j2yHp0qjqleUWQCgTKh\nh86WMiJApTtlIgqOBwfl9hXi1RRhg1yKAYgbpmL4wshAZsb+8Sf0Qyn+tZPQ\nmvBkzqC2K6k8oMBrLcHIHpjPY5tv6xTzk5ABtG0Ve/U6o5p39PGxkMzDXvOY\nmchTQHuJi5P8TTQp+Nm1/bQaqjE/JkfQqam3zAnbsmTTPs75eVA6QFtCRl3y\nNwo3j4TU1OYQzfIgndLDb/ZbJmXxNobAoV9yL6e+uigmeeIkIavj6eovaxUe\n/g8qemHuOJJO9lhWsKzyXD54okawyVYvbClDdaGDu950UedaKhf7zDlD5NCq\n0SEtnfBi8BosT4Q8OaspKb641yVp0ZDeV2xdmupWO8Cvs4yDqrBC7/f7kgho\nNrxad3Zljk7eEmKaHMZ7UWMp1lqahrKNlTiOUYO+tONs3T6W+pWvgLzKWdT2\nBgXH66aPohXt7mKM/dPaLJvT7DC8yF/eAnDTeWu9Z0OUQrJoQZroQAk6up+f\ncuI5DsAKQIs/NMSKEtsARYSAS+6q606qfTvvynId+8hXlWhPe53xgkvHl4BP\n9y61nqayNmHrl/f7Ke5BDe/PSUPDDCvLT02XGC861IMUIPaoG4SHVfHjy8Km\n+rYBjk05gGDYSnWZ62O4Wm2A+ctNeOP2pCK5hs8EHpvPt/hRzOs3kojHoDDD\nITB0\r\n=wJ7S\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICCP37T/CaiAssFzpgbOTFoY+ocB8D8zdmNUhIO0WahPAiEAv9SZdV61dkSMwCaZkCQb9eb5ioTep2LTJdCW+9B4xic="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.10-taskrelations_1590472993303_0.1864088526133838"},"_hasShrinkwrap":false},"0.12.85-alpha.11-taskreminders":{"name":"teambition-sdk","version":"0.12.85-alpha.11-taskreminders","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.11-taskreminders","_nodeVersion":"10.16.3","_npmVersion":"6.13.1","dist":{"integrity":"sha512-1zBP2K9Qax7yETuBAiwLVKvw0N40ABomQTWjXQQ9/RixcAEhZAxkzxQed59vAK4QdnzmxO+iqwg6L3RrBSlLgA==","shasum":"24a4cd01bbb83f8492f99f749b50290da35abac5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.11-taskreminders.tgz","fileCount":512,"unpackedSize":1056148,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezgEnCRA9TVsSAnZWagAA+FsQAKCjz0p9QcJmHkP67x6M\ngJn7iti+r3pemH2ki8i6xz1jD+pEnqRQIVSEWjX2wt3vMncSK4PVz7H+12qK\n+Rfh1YS/+sWw1PtN5LPIzCIvlGlaUOy7jHkgQrOBBDb+Poa+rYCCLHrj5bf3\n2MsorGURZWWa/MTmGaFIWjfqJFdETKod2OYM1Rlq9XNUe9llBqFreoRdNrLI\nkvftc60NKzGbYaRZGyg1YRbbjdwM/RaJTacObtRQT2Po1apG54xdaSZDMe5u\nUmkCbYWt69fW13c2SfaXPaoVg+in73XDyzgF/quhFOXhP2Ke+Aq+k8xoHOtv\nGC/jzbWb8sITbxALSHn/Q+HuR8KVDnUx7ptmhp5rXKdlFJXzgdxKiwYrtwZ5\n7k1vwDXmgh0u36gIhactXJTWLWvd4tt3IvIcfYTS6Ci+yJ+3cEUViNkOKvq8\nYdJuBcaWwFcC0ZO4rZJ53J89vgtFCS+825S1MR/lhO2cQjiU8ASrSVjw/gAb\nk7/yqJhDVzfthVDB822r+rt96J1S9BwVjESLjHDYV8FBQB+HfxsLj6NM9t2b\nqlnVP6l3Hysi6GG7mT3ysV22gtMWVCB3FzGyRZFUMhF+NSTryv/R7MZvO2Cv\nTR+e5EhXSFR7hTbW+VzMQQzUuLcA6PeD8PbyWcu/Mma6WpO9XYpbIEXU6ofi\nNJtZ\r\n=wtso\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEQrPaTyYBP8Bhk9PC0DCXvVDo4CMy9Vx6ei6mi3lFueAiBxn2oBFVy9Jyc8MlNf6yzJSSPcxOp7xOwOr8DmzJTSlQ=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"jinchang","email":"chang@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.11-taskreminders_1590559014882_0.7560675128308993"},"_hasShrinkwrap":false},"0.12.85-alpha.12-taskreminders":{"name":"teambition-sdk","version":"0.12.85-alpha.12-taskreminders","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-alpha.12-taskreminders","_nodeVersion":"10.16.3","_npmVersion":"6.13.1","dist":{"integrity":"sha512-LfW5Jw8YWwlQCf07y3p4mOR0owQ5qLxcjpfftm4E1wZPRohjvb9iHhhiRWfa1aQ+q6J0RUMI8OvqJbHYqp9qcQ==","shasum":"89f4f1598b22f07b4762945a9aedd66cbc82209b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-alpha.12-taskreminders.tgz","fileCount":512,"unpackedSize":1053317,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezg3KCRA9TVsSAnZWagAAjB8P/2Ra3XuGrIR77AiE4D9P\n3pxiHZdBMLHE7n0bdrkRr8oYiy4DkVuKYkryK9QN0Jgvtom2j4/YM5dj95Jx\nS2B8C5KKDObPZvgHyhwHUPZY2cNqWJyXLXynPIm7M8t00IELJ1k1kI08uwUR\njSuZVtTT7wzJcGEXh2yAQXz1oL/ULcEoSRfhtzpZ3CIxfhyaEcgFxiVr/whT\n4ATGCOqUQ7CQvSPQj0WC7ih/NCFJX5JrDll5X8ZYsHnLaJS/ZXFCjZRZPGUZ\nbDs9zzK5q8XV3kQwHnha+/qOzv1U1f4TkD+kGgS4C8G4YkbjIS4SnJRhkH5d\np5WejxJZePuoN9fE0bsi+x7MirFLCyMfQgJUqO4PaaA/YtCZ1dwT3CXGzRfr\nQPF2dHfFGugYRGn1WTBJI8jV9o/Snn4jjrwuuogEHTVlrbHyKnlcUb2XNlcm\ndLHRICPL/Ub9qWvfwshPiIX2v472Jd9VPS4US54m12q3BAk4CQ1q6VNFBFSw\nSOdfOjIRmTkh0paZ2brtRk0gaa+UXMg2mFugfaJ3023BVL8AxC0FE2XTwkBC\n+w+zoftOalpgeQIzjVCesU+DuiWRMiKy+7/nAWh8dGofUHr4KEbdJ+yh3//G\nI+zxPWgC9t4MaTeISVaqUicv34fKQH1Q8n/xNrdVXy7jovBL/sOiluck+dcQ\nP2Yu\r\n=pXBf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDYhlAhxMocuxlxYfB1TDoK1A0iq4MJr34vlsyePXi5xgIhAJLRe4nnHxcvBSFH0YjAQ5P7vvYN05/MIQWbMnDC1//U"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"jinchang","email":"chang@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-alpha.12-taskreminders_1590562249912_0.7809886637809509"},"_hasShrinkwrap":false},"0.12.84":{"name":"teambition-sdk","version":"0.12.84","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.84","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-r2rS4cIJNHjLivAghM84rXX7aEpoC2WvIEcsdWK3WtZqgl4WbwBXGd+3sXo2vSknorHiDpYZfjUkvBeKkJiZnQ==","shasum":"47c461d8d4506a42a0232a72ce313e56f611b70f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.84.tgz","fileCount":497,"unpackedSize":1036936,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezg/yCRA9TVsSAnZWagAApWkP/0lUhPIq+68X6ZjINVdw\nOzz+HfdWjwm4EW4aRKx5kCYKy2IzRLZllEnpDYV9i31GygLibPBpuJJJzmGo\nYz8wim4tovtz9SXM+68GH46S/MEFvR2+1ADdYBdW7hJj4KiigLmnLx9pNpEI\nZgwIbrjpu5k/NbY8L1gJNmbppt3SYt1vJ8CZnYHo1b5eg9h4NnYh3YSv0ok9\nZaGyY5CNqA3BtB/FeTkzfH4dhiOzxdg0JRktLLDZsDxaKgFEvJbiWcx28mnV\nvX6Tb1f6AFA1u/Vuxk7KWZJOEJi2iOleOP9k2wyiV7DPrnFYoqt/R3eyigX7\nzx/R80XoEjd4hKrAOXTZQCYo1K8ARqVongHBpGOY0t7C1kJZ0BDXvxhjcT1a\nmz5SRFbfvDIdYfe9IaLxxNa5soKSQv84H1b2e+pMW3/rwYhYB8tyCA+Lf4gD\n86bKf8OvI6XLodSjo6eRY2oklH1TrbVsYDZRU1ieAWTQauL9qw6s8dg+rSjf\nTPYNbs5pyqAmhp7B6h+orjzHxcm53b3E3Zim5ec4VTbsyfo9hMCpFNa9FMW/\nHskUgiyRSacIotRjw+q32LvsvcqccLb6T9q2GdsgdKOmosESip0IIGdvuWsE\nV80zLi/tGc6Y7RPpnQOOW9ga/y7vBiETYTg4ig8Gk+BhZTQZskUUAWXmF4Jj\n2eyL\r\n=Eb5e\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCeHFU2p/Iyocp8iollsJiQRGDYwFnhHgEgFHbowq0J/wIhAOjbG41OcVAXVAue0iJIXq/VMSc8KVURYQf864h4j1aG"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.84_1590562801348_0.7922236706215924"},"_hasShrinkwrap":false},"0.12.85-beta.0-taskreminders":{"name":"teambition-sdk","version":"0.12.85-beta.0-taskreminders","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-beta.0-taskreminders","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-TPPwobJUknt1QH9VKvbObc2D/aLc2JLYxAlqxEVm7zbadmFLBSEhYfj4ApwaRvevCvcum3zOxkLkqPNeDwlnhQ==","shasum":"cfb0fa257e14583b07fcc12d331ac38c999557ea","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-beta.0-taskreminders.tgz","fileCount":512,"unpackedSize":1053470,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezh/DCRA9TVsSAnZWagAA5J4P/2WKjJitLGj0zdxmPZ38\nysLXcCdyLPRgrqDf68zKi+byFfXLh/foMhWH2eZnWT4AzWp+F+/skrKAMD2e\nUm9PIOfFp/4dSkbgiRpky25rD0DkRySXFT8TWV/fGui1EONwv1041FrrQzPc\nrF5gkrUymp1t7aC4nLTW90xVr8STIkS5UMp1mA5cpcfgcE6TRk+RmjSlIvNU\nE8PcxfEPC5rRoRw0ctJwNh6e/IdYOQId2uK0IeAbEl8505AU6uOdRz/daQT9\nYsrL3c8qsz1L3BihVTYeHZzuDrMNK2xiFD/OKgPzNsmp25sACyTfDZZLB219\n0p5st6ijiNb4OWbC7Gjbs4FzHPq84CIOOG7fCripwD4YJ0Nj+4DeKXjXhRtS\nkNx9p6yVOCKj6Vp6ONs0f3EIZUH1Jt9BM9dnjbVZ5Xj6sYmxeT3mGOZW4RfJ\n0o2FElv24ND2DnXNgExifEbyFuFnwn0evCMwAs7RqRQ19ectr9wxGo3fFWdP\nJTfgMzYFpj0xD5bplXHd78NkFpy98ZmxPBPqYdDg8ZxGwaIHFG5lZJPxstbV\n/Y0xajTNkqUthSNLSPBOUgXh2xGDUeKieHMHy+PctPwu8bFxZbMnNUNoIt0f\nCIRd3UBEOxbvA10QLX5LH/0nbFqpnmL7Y0ejsPGqO5V4DVQrNgUFtQtp35Bs\nv3x4\r\n=Ub3n\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG925JTK4ZY/IQbJx5JbHTXXCkf0DQ/JDseOqlPX0usHAiEAsEUxH9ifB0tdmvD+Lr39VZmd74mU0H/9INR0unz8Ipg="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-beta.0-taskreminders_1590566850834_0.42587977368297003"},"_hasShrinkwrap":false},"0.12.85-beta.1-tasktraceobjecttype":{"name":"teambition-sdk","version":"0.12.85-beta.1-tasktraceobjecttype","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-beta.1-tasktraceobjecttype","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-aAz1Sq/vrj7VAN69d5zd96qxaVT6ufXufAep2WZvrEvbTRqbWBf9LYWVXWELlZ2fw8S+HwV0KNjHsFJeW0W5rA==","shasum":"c677147f8e1e1e673a4eebb9044d3db047e7616d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-beta.1-tasktraceobjecttype.tgz","fileCount":512,"unpackedSize":1054615,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeziyfCRA9TVsSAnZWagAA/dgP/RROCFb40ymG2U8stNDk\n/4OM+LcVpZ23c2JuRQH/6qa0VbL0AmlvBqESccIF09v/gxwvgEAXXL/z+c0A\n2ZJdI45oDfmAo1RofvJ0h2ydmJFCaNbL68GFbTqklOjzNV4h3S9aVgRpmp0F\nrd2zCdzU4kul0nXU7C/rDmPBf86SseV/5EwBxBkCC30Dh24u17Y/LReW6FGo\nsSnydBVsjMHy/geJXqM8tsxZkc4XgRNv5ghNzNx/VZn9mLKS5TLGYBML+DRW\nGGhziv0aVTBhUsFdodByy3ULxPFLSG+0QwYS28Bw6Gf1x+a71DaZPMqWC7xP\nrkxXUC7VRSHmvzK4vdCDS68US53CkJtzh7O+ICUaggK6cyybGNkQxhujlgO2\nCy8ajmPrEmZFZWu4pVxm3FLvnZk9bdEx1P5aW4U22FlwhobB/Ccms82MfSg8\noKyxtmKBR/CMEb7Hge/mdnFRiu7ie0YSpW5aVvpyNtmjstUNTzNmiTi47Ihj\nbqJ/YN6YAB6G7jywF+L3ir1m6BB8u6gqudet3hp/wiWBcTIKVX3k5DMnx1cS\nhgqXPrxbI/gFIB9C6wTM1uLuTDNjAwgmXS1g5qMBNDbrteCF5uM11rvkaIxe\nB/gNjvepBT3FX3ZYpiug+2yYicpz3SQNeYKvH4GD4cJ8sD4xD/qalkQYdLGN\nqmrs\r\n=S0no\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDmHhMsjSpkqtlKtBJEzrLVpBBQuTcPyfmu3beDSrERegIgfhIGOGkCdPks6haOcUB0NWM44lRXZk2/Vcw36UuH+LI="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-beta.1-tasktraceobjecttype_1590570143079_0.7617511444318794"},"_hasShrinkwrap":false},"0.12.85-beta.2":{"name":"teambition-sdk","version":"0.12.85-beta.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.85-beta.2","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-ukcrOUanG6y8pEz/mZzhbM3ZTp1BHme0v+q6IxxFIEpTuAZuPtlPGc5+rg7dANDa7ZiIrgdyjlofJuVrGU7b1g==","shasum":"659f321b3b432e5891c75b3ae48e2e3573ad2d0f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85-beta.2.tgz","fileCount":512,"unpackedSize":1054595,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezjrLCRA9TVsSAnZWagAA9MAP/0TsdopiFfhn5fPv1spE\njj7gvYw9pfnkYelNK0Rp4t/MNeCzZZoDNtT1N5uQ3n72JJD+9jlpIrmS/vle\ntqCfDO/EyYtszY1Fmg15Giwe/4nVz/dP6o7bNgZMBQ9ldCyJ6iApWl0c0VfM\nsPpec2gtE1jbj8Y2dZ4Qr9QVsQ0k1FQke5u4LGry7xGAZYhaZXLeU+KFglJb\nugKL+3DMYQFOoIYxaGM2+O066UdCzHTnDKuLx3rVeHJ8IswKQIyqkJAy3Ss1\njNQ+a2ZOmmnIrYVNtpTWrdP93Fosi6J4510MYnPlyrm1K5RnaBRzqg3koBGE\nGo3mdEhbX295D2ceawPPOc9zSKg4GNDkHPbEb2SHzs5eBFBjOMoikBdIGR15\nyz0xx7XUVDK8NEsONKrT0dQc09/NScsxMrCHrXNSY7P/m/Keb8ARo2Rt0DbT\nCCXrfsasOpGh467SnOXyMDi0bDiyAUT4tVRlgbGeSoaF9jpiu95YLwHuukdP\n+dppOH6C1QPsFAuS4AQ+EGI8fUPbZhdZVY0tXFfuNQJIcy8uScCfqAh4uuVc\nm9fdjElKNnkEpWMmHz4l2ZsYCCq+xcAF398U8nsDYJR3HU+d+aZm8R/JGUQc\n/0zQLLNm6DNj6QHNWBDkCTEK7tZECLSGgP2Z0jUS3/SOB07W+A2zg/ZDdhTx\nsSyH\r\n=YuDR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBJMBiI96btOdgkl1a1gP76YoXGPfas2BxK2ZFXbbmeKAiBWBIBVrJ2VxQQ4ovn9YuMEDZHqLSbJvg9qVNJXU+tQHw=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85-beta.2_1590573771202_0.7741160461689982"},"_hasShrinkwrap":false},"0.12.86-alpha.0-taskrelations":{"name":"teambition-sdk","version":"0.12.86-alpha.0-taskrelations","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.86-alpha.0-taskrelations","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-9KNU8XTH2BjXLuiaTkSh2tVGCFqZUOlqcpX7Ml30jKPsaDclJi6uiTw6aFEvej2nxPt7Yi3MREfqQzX7Z4a/zg==","shasum":"e91df8701dbec027f335e92091d33e4470cef456","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.86-alpha.0-taskrelations.tgz","fileCount":512,"unpackedSize":1055680,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezypOCRA9TVsSAnZWagAAH9UP/RJ1oYcHisTvNz64EtVB\naJjO2wqN6RJWnaSBm4WBawDyHbrnWcZ/XiH0nIcIDcZJOZpj1uORv7L+5Mnk\n+d3me2YH13zqxMUcptO0E8iGmbhGRr57pIeZ2hP+Gkr8gxfgb+/BCwbRE9Aq\nrKMQ1dZqp5BKvJ3kxwAS0Oyggq0gsTRd3H4Mp6cyGb/9A5hYV6w5xUL+6cFm\nXtQybZ6Gl5GxQRk6ls6rECchzQ7whDmbtNutEQfIC2Qh2UpL7irtYym9kxRN\ngEMybUSltiB2z1bKdZS7LtIVTOSV828V5xy+zcqE9493gmoZ4SbTKycdl6Bg\nPtY9qQJJpCYFqXjafiHNqtS9e03Ypz1nMEl2zRRPZDB/nSx4GuP6kmsHvarO\nTsHTQpLv/5Er9Mrq+8AN77HpRdh6i/yx41DQPFaWWc35xF8rtAZ2q2ymJGXU\nviU0eoWq794fi+/XktQ69k9kMIQjwHe91WOS4qwxr9F3Bt7hQugnLwE8xQh5\nLKjtQeGJOuJVmZXQT1GF8tJOBCEuowGDbTORL+OrZ9VXMFJiSuK7de7OlZO5\nk0K2RMFE9DQH3SojZCk5iO1vUVK0g1ee6ftDdF00wQ4599iv70/wISmRRnVE\nkqEnH/20/+aaFcpQA9xXGYzztDcx+wQdKSj/qmWjoFYrbOnyrisV+Q9bhoY0\nZ5gb\r\n=rIM9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHcXwkyQIhWoDKDCGhxwN21e1ATJdIZ2pe7T6RfAm0a7AiEA+OxFtesBagoVbFIrGXMA8wca6DsFSKDRmIT2SIkr8Yo="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.86-alpha.0-taskrelations_1590635086127_0.9376373496710679"},"_hasShrinkwrap":false},"0.12.86-alpha.1-sfcbasicfields":{"name":"teambition-sdk","version":"0.12.86-alpha.1-sfcbasicfields","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.86-alpha.1-sfcbasicfields","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-qddvQpDRHuXVhF4lupT4o8XyiZ98mIxph1o+nzDKZZVKaBei/BGFD+WHrRxFvNQJfQredmfZ3CEW+hw+jrg3hQ==","shasum":"ba6b7d1f45ac0b381331066f43c5a3309aeb8af9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.86-alpha.1-sfcbasicfields.tgz","fileCount":512,"unpackedSize":1054850,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJez0OGCRA9TVsSAnZWagAA85QP/jIFNGlGJ1ZG0cpANM1C\n52eGdUmPIpuL6UJK5e16q6Lms/V8kQEF5lx2n2Y+9bKJ2hdg2EmJSi6+WwqH\nFWZevM+GZ4s/wNG3k376zig8OHU33V5iAqfGyy7nDoO7fvSDBvSqsGSfvlib\nRVxpjKGnIC4D5noRflWzeMtpJmCN55HUj7adODtbmVfibNGZX1tV2tffNP/0\n6YqkuMTT5WBZ1BoZvloPgKZn60dcvmz6/JTWmLIEO+BJ9nMSi4J8D0U41S4P\n6/FGyHaXkNl70rFk6UXaD6gUU43cGAwTeOJwJPC/Svb/DHEUbbSltumbDNUN\nMi2diSgro6ziwI8/AMmE6rUfmvgMzKlQbkJH65byYb2EnDy6IBqzE+pcQXfx\nL/ylt5u1ideUJzPWAeGQfwzHVE8DBLMXlGYwT7F9kiGuKHcNihu2lVsxyi+S\n6Wj4+Wk/NZmKut9LO+MHDg6onxSJzKGH5YOgCP6cuhvFkqU641js9ZzXCwYv\nSifSJYuiMyB8SbpjemoVD5ZdQBEWHH5/WhRua489iM7WAWyHLV8w12iekw3Z\n8ipVQ1u8hOkckZ047qoZD3Q7OkxNEQi05K9tV8evz7h8mNEkMHSHCqSQSDvC\nm4xZLV2cOXWZTm6SSLAdG497ExykK8farUJUq7KR1JYKMYIEZcpS592wVk/g\nbuhx\r\n=q0ce\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCsiVVT/GC68ap4S+7kP5oYloHWdXVWf6CLN8bG2UJ7xwIgPMqH6K96IggsTFb1dVWI6es8b3y7Ee/WPrXv12AoFSY="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.86-alpha.1-sfcbasicfields_1590641541828_0.080279562945335"},"_hasShrinkwrap":false},"0.12.86-alpha.2-sfcbasicfields":{"name":"teambition-sdk","version":"0.12.86-alpha.2-sfcbasicfields","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.86-alpha.2-sfcbasicfields","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-QaHZnxjTEScmWBBGB+K2+V9vTfQuPkO6D56/3Z7fSw1XNeE0ba9wF6Z5qWYhNgLpsFqXJK028tpGPchfZmOZJw==","shasum":"123222168290a2d9e9aba108a771f20198867186","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.86-alpha.2-sfcbasicfields.tgz","fileCount":512,"unpackedSize":1055428,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJez4ORCRA9TVsSAnZWagAARTwQAIeuU+9G+UIAlL8/I7jy\nRlfUlATVFLnprjPjeAu/gNQuXR2/Ql+6ePvVFXmUm87KZy/7uPwRG5d+rAX1\nH7qKU8n609Qb2rPi6YniQVkIq4+ZN3VAAt3pkIhN6yRcX+qcitoqt+AmI5gB\niUvxWOHIIwkTWrHdjh5UJn1JC4qMK4mpflm7EV8zMDHxxEgMQ1a2HdHeJ8qv\n/nlxBVY8CfijUeNYA/yGvK2KbNExeb8R0g50AZXtXvLKgD2/14cFvQwx3Grv\nG97+AF82zcjMQI6ecyMhifeNov01BhCKRJUIi08DorBNsadmo8hDSUkwHzIX\nTKgKNwgEYhpHI6dC4pfDqOuOVxhrvgec45wte/BWYkhEUf9wpe2Nt/QKwoXP\n9wjiO/GjBMxz22dpXmQIMgwgOqhbppT+PQ1U8cUyiujI8qJNmZiXFx7sDWcz\naSvQNYZ4W2oNiMmBVgGV4ErTkHT9g5EvUVgTufhOauK8ZepkyrlM13o6ZI3T\n3DLMODyFz7zndq/nNUm5GCUEdVZelPikPsOGIDluXKdPzjuM90x3MSZU3JJS\nrTh9m1H3hI5KnNis77yqgci2zjD0wFQV97PFVgTZd+OV3N30CTatwc4Eu171\nkxXvlAvRoiJbX+lPr7qU/S+BVTtJS4r1mf0cb7VutszEMMWwSs95/h5XKqCa\nqZzT\r\n=TKjV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDkNiwn3kOuHQrbjqLoFUT0ZtLd1i/1+LIu3WG9+hffmQIhAIGLhUt/6gk666pL+7RGREUnhdPN4U5/RBdSln943Nj5"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.86-alpha.2-sfcbasicfields_1590657937022_0.07642479076120523"},"_hasShrinkwrap":false},"0.12.86-alpha.3-subtasksfcids":{"name":"teambition-sdk","version":"0.12.86-alpha.3-subtasksfcids","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.86-alpha.3-subtasksfcids","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-xhi7OJWCnwCKxAk9VjBpXHFTDmd81yzR43BcO/uF3Bb6gyBQUHiZlKGwfsgPKr31oMYnopHneB4Hf/gjhNFySQ==","shasum":"980b01456dfb00ab7f77924ddc87cd5f6bdb0df0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.86-alpha.3-subtasksfcids.tgz","fileCount":512,"unpackedSize":1054861,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe1xJmCRA9TVsSAnZWagAALY0P/1NrcadO1trXRqfnfmjA\nwTdSmaCNqH+N/IfsfG7WDHmofoaTPXELT3Y4PYdF/pwG1hSN0eRRxNnuOn12\nmBC8+iwiDS5KDBJejWDEFDfD1sds9X5zrAN4i+roV9+/L5o1fenP2OU0+Y2g\n2ye4eFKDbnpKYllQLntievewMiME1osBJrrHFDnrWz/1xXDArgE8Rl+ijdY/\nHWL6L1y9aOhqBkkvGUVB8+28fHrlfxZFLQ9+idjtSCodzi0LgmDMiwJFWM/N\n9Fu486F1+Dq5JGcUX45ga3nTlgY7IdvgI72fYRh0nopDAYotm0evpyMF+2hi\naD8KHzHb7pfp6EJdCw4AXEVkr3z9Oz8pg2CObyd4Ay9UbKHKXEJ0ta9/t53Q\nSDCw5q2CSQzDOnLzEXe7rR2zPg72nXnfDWcMc2kyC4E7NkBT6CmBkpBAPGZ/\nSf11uthWxgtG67t2mfJcV/UR429ekWoEh/c5CLwAGoeP9RI5ETjEFwpfNc/v\n4spTWd+EEyEfktYrMleuJS44e5R720grMRg3GxpPP52dYUw7lRXlSIsp8IuM\noJOz9YGcTXc9rm3LisjVsaHrkIks0wwCsWzgrXOk17WMhIo2ZIDbusrJvAd3\n1WIH3xYTNJRubXC0BpUs0TzJYcRWVR4h0BWJ/W7btmAuOcSqfkb+s/avrDW1\nABHq\r\n=oglY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFXEoPRCgYYcQzCJ0ffuGeR0M/WvIq/PH3iL01Piu39/AiBDRToeXfy97bmKePTOMXh3dbqIvX36t3KPGOQJ1t6OtQ=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.86-alpha.3-subtasksfcids_1591153253847_0.4354015853912101"},"_hasShrinkwrap":false},"0.12.85":{"name":"teambition-sdk","version":"0.12.85","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.85","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-fbJLosz1GvdYZRFAJU6HhqNAhJvt2o4cklvvTj7jnu4Pw7Ot6j2whjxobsaWnEYQDxzZexPdrshhZ6BS2c2asg==","shasum":"51c876ac204183a70f7491177b55b6f734621a66","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.85.tgz","fileCount":512,"unpackedSize":1054603,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe11BrCRA9TVsSAnZWagAAxhgP/jHGu7DZKxaNMUByzZBX\nsll0o+Z5i7XDxLhq+X7Zqc2Im9xSeOcHJwOWVnXbpoTmvLf8HaJbodf1rUa7\n7Y8rz31t2itgQ1PtZRLGl0LPXHHyydrg3j3bttTajvoQREl9aYw1mTxdkHCl\nvVIGOw5SPCiF+H3TrBcFRlpr1BomsBSuADkeGovPV5DTUUX36CI7rhfm24/A\nbGO+bifd0+aOBNVPR+UVBH/nActc+rUYZP7XuG3XgWDvvqk0MXfcrTmfzkms\nY46gDQ77URIvmydvsjTD7ZynOcw+JL6crKKrL1L2SFa0zdpziPnrQ/A31KZv\nbmRh9h/0KmVhUKIZ+AkpzB3onbC0dwg97LY0dsL2D/QxmWR2Nszf1VYSotvs\nEkFxE4nEfcoH/ANG1G3AK8CvMGWfW4roT9GXaBEcl+UWRT03+EhHp4Ma7YPD\nC1nWeDg3Juk2ScwLavY0jOK/HYUCF00UHeZfI9R3QqPzSfDOw+FX+2xivGzB\nuKozld5RDNcW1fsa8BjI20T6FJg8s/tyCxtyBfm/QRyhPE2tFAqeQ/fbRF4W\npGRbl879GKjIBN+KzpJy6DVcsS/kiQoOMy2PRuVW4zAi3tzJNtDSDsfZmvE3\nAOOvwNAFViERl2iU+JrAV4box0L0sakWoBuKkqR491Oa8kMnVdN8fGG/frMq\n+1UZ\r\n=jtFo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAJxyq3ZDCWpSByOCCqubsrWekbPBkZVo6K0slgUV4KuAiAu7pq7mVR3JTw7lyHu0uBEY6pvE7yWrrYPe5Av8f9nVQ=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.85_1591169131032_0.20964562832675426"},"_hasShrinkwrap":false},"0.12.86-alpha.4-subtasksfcids":{"name":"teambition-sdk","version":"0.12.86-alpha.4-subtasksfcids","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.86-alpha.4-subtasksfcids","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-PqVNLbL+Fmw7rP/0qLeZoae9dd+r5xDDpcSytrpDpVBx3CFhB0IbUYDHb5PluSjdJaef2+9Zl6brA2Gx4Gixhw==","shasum":"c6505bd132da67fb6b81461366c37d986160870e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.86-alpha.4-subtasksfcids.tgz","fileCount":512,"unpackedSize":1054704,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe12+tCRA9TVsSAnZWagAAWm4QAJuHSH2WVxQjhLUrRoHB\nFdtAXGxRalsliAUvbR9993KbJo/6K6Rrw/TS40FZ8BtMBUipBFJ57F5DpA15\nSDjGpx2IPpNYb3I6w1CgBI/S9q/K4+hFLFuDl8SP099cUjiaGHbZOsM9KD1a\nmEP6XTx0T6+g2jHlZ0u9isrxTDgXOogPzJstRJgou2PyEBYoYzp80jhARTiD\nU7t/VZlc3r66GsAeKAPn5oQuduixMK/YH3yw7Ug5Z3xnDdx2xiq4wHswDYJf\nFMSAwAh7mS0erSR00DN9mPi8YHlaA1tBmDU+1+s4PuFN5bAN4zPkPu1AnFWm\nWzcg+kWlUT9AVv5XluCF1K+k1I8XMUytlu5knMWHumzCECCA4/4/sZvuT8Z5\noQXs8qoopHmAtbwm8Pk+jke+BrlC6Us72a44pzbuoKz6q367LVDbieE5kAqT\n/7J+XJ4ru+5Yi88gFVhz7aySjn1i6k+OnV+4Ko0w+BD6sNCtVXa75o+4x6Qo\nrmEWm5ehVzff3ObK2AnQCF0RRHcbd3gE0YjSQKQddkK4sLLVGuWe1gZVXePt\n5B+nyCE4j6pe62oyh9TiQIJ1CbP3vmTS6pHWtnGwlTsF0TcEGEMSohla3iyP\nzyeE5GucaRCibBzkindcO0OFzrCU13eNbn9FhfCeSVW25cvBzTrX3rUgntwe\noSoz\r\n=T8OJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD6ZJsTl+X6V2wyT8dVHCl37YiBzeQWJv3BL9VLaO8AAgIgMEK4+hqIS1wJ990bn8ciUXPLGNFnnR8w5KoEjsyGpTU="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.86-alpha.4-subtasksfcids_1591177132440_0.2246983118551249"},"_hasShrinkwrap":false},"0.12.86-alpha.5-task-relations":{"name":"teambition-sdk","version":"0.12.86-alpha.5-task-relations","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.86-alpha.5-task-relations","_nodeVersion":"10.16.3","_npmVersion":"6.13.1","dist":{"integrity":"sha512-9+mrAHhz9Ebt0ViLqawyCaQC2N8HFK/0K2ExIWUtCsFtXS/I9PSPMvrV0P1IDKncOaOH0jdhxPxx5zE47OVO7Q==","shasum":"300fc65b48a1dfb9e5a84b505e9794f7767f40a6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.86-alpha.5-task-relations.tgz","fileCount":512,"unpackedSize":1055709,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe2gyYCRA9TVsSAnZWagAAb8IP+wQmJjyZOy6/td3Y909M\nW5xvYIBDJlQJZPCU96Il5RHarRdzaACQRinUvxlsx86uVJ9oUIeBQXwRxq48\n+7MVDizK6gxQvug4m+NbNT7ksJ/v+SxvxkaYoBRlJhvv6zf/b6Xe4fFOyvmy\ndaCsWnE63wWxTNXX5L9t01fYmIRGon8W8vZcuoSD2ifEqiRMsCt+q2WYJguG\nPWaPGeNUC0bGU9izUz5+RalWChj+6KFZNSaKNN91RdXt9m2i2gVS4ELKZk//\nsLDx9IuFOE7FLYhyBaF67w8iCPTce0CymJUMcL3PX7/n5lixcvAQ4gb/uYHp\ny0WG9KTQHxOJ13mHvcLVyMx3mk801U2ih8qMqBwKr/NdyEmi1PM9GIUEDnDg\nI1Kn0qWMTM2jJYtywo0sEV6zP8sLrdQrSW1HLkZs4iqZtAR6qusEcec3ilpP\nZuk30KKRNv2KjHw169y6kUtHTMyLiBOioch4+Lzt+2STh4QH39OcSSrPW4ya\nf0p7oxlb4L7eySExdDYCKdGj9CmxVUB7Ze/+3Nq9vDMRKccxS9+zSPkEHgZK\nwUmInqykswAglnjprB+L1WoVGQqiEUm889VeiJ7g1oCtQPzii0CYSTsKmQXP\niYSU5VMUzQwg0cATtCG/3n8ct7/UFAi5T8Zxy8uesa5XOLPMO6im/0nwSfX6\n5t0j\r\n=aUI3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID5Jm4JyG1KenAox8dwIM9fUZYnkTFzO7acBpzMySJvOAiEA8kLRnINGcFoscJokp9N1mgzvb7OPDRqqFtdzS1nj6Zo="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"jinchang","email":"chang@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.86-alpha.5-task-relations_1591348375582_0.45905599265249575"},"_hasShrinkwrap":false},"0.12.86-alpha.6-task-relations":{"name":"teambition-sdk","version":"0.12.86-alpha.6-task-relations","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.86-alpha.6-task-relations","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-2c+W/riS1bRQ5lmZwg8JAAGgxx73/i0+gFkKxnpapoIuWyQHrYtyztBRfUwUmzluh1y0HtrfpxGt7UWtqY3s/Q==","shasum":"a8588a9a762b1dd7306a4a45e9bc1fb0ce323050","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.86-alpha.6-task-relations.tgz","fileCount":512,"unpackedSize":1059486,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe30FZCRA9TVsSAnZWagAAa6EP/138x2ZCJOR7UTNEa+6s\nqtSnNKF79giOgLHDlF5YRc0efSG8nCq4xUx4E5TgKsRjpuKmB8EXJQKBesEZ\nspvdTi5Rz39cexhahzYggqlkuQeYYz4JOnKl43arqOUijKg4Le6tc55s8qXQ\nXpnb2y711J/ZVde9odY61v7G1CsOOIAuryKW4eScXHFgX5JTocjRwv0OvtU4\nZUstAhZnmX9Q9RUxXWAHXXQoCrj9Uc/v7iyumM9uBViW1bu/pIGTjmkUXsXp\nyFUFXb6Sm9VsieKRfAazOpmi9e3fuX4PEoQ5ocJJ/rt+C61iQorVRtVb5WBj\nUsCaNNROJkeJzRdz/GLnirZsztJMPS4kx/sz3Y2mArgiV05tqj+Kr8+5bTVl\n1U9v0cHIo6WqlaTsv7hYlBqRVRHFGkFDL/JJrb2j5ytkTj7EablFhn8UEqpS\nkL3CXoNpAbuFrn7apLX/BenNbRYdmln0BseE6O6QXmLIym5xLBQtAQYZjZ+1\nEBsTH/r4ck7re4G/wdcJz5RI2RUi5MJ5YgtNF6pXUkWoah3o3I+wUj6r69UF\nf1Wyr0bX4QrRNvYJYLMOKrisISB4/fElms00Z4IYwjR+skj0un59l3dEREiB\n4thxupusMEoV6V9eTO1vlheZ2idQ/oqMJAL/eLSbOLhVCsfuPrnoKyLtFAhk\nPksR\r\n=WGKi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFTPZryosmCDhxZYpQVBOvip4x6jJVwGsbdF9q808+SnAiBBEi1/+PO9bJrslZ19pVFERk559hU0UoIfvf5mHLjTyw=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.86-alpha.6-task-relations_1591689560993_0.6567269303137007"},"_hasShrinkwrap":false},"0.12.86-beta.0":{"name":"teambition-sdk","version":"0.12.86-beta.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.86-beta.0","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-quFaaZWok9z+DrCgXJCEDasQbBIk92/BNVMz08aRJi3md1Dvcm0UzndzXbkKqDkFlBoR4V6pa4zK+0Fkag0xbQ==","shasum":"43797fc27f086d5c09fea71a5c046f1ede68ab64","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.86-beta.0.tgz","fileCount":512,"unpackedSize":1055802,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe4KjQCRA9TVsSAnZWagAAclUQAJJGJUCHWR+b8534srfW\nOUJnNf7p/AAvC4iMXc6VCWq666LL52CL82yF7FE2/Gxsx5671CFd9/trvq/b\nK/yc328cG0EhcPwtn4z5AgSyq72F113MXt17uxK3dI9wkO45M9f25DbqUNvE\n4xTdC2kQrBTQF1VDafxBZrqPrlWwQJqtl0H7eBpJpOjDA6w42RICgPx0L9TK\nuZ2oPu9pNatdcT71daYEiUJE59uAcy4ZPf8bmuwRbdzCxtkdYNt3xwvf8YAM\nQ+uMMgNTwgZ8I6paW+O0C7F36EKLcPrLGK0idINOwIKeJm/8eK2yloQoA61O\npbQKgTN0dScNg9za0vNqczL/0L4rFHHLk2+QOvU0gt0RZpKCYdqVemEcN1y/\nESy47kPMU9m4CjbS6S5jM3uQLeMU4EJR5uwHnBeW+saaYl5zqeflh2A+OmiL\nUgQEjk4snaTfuVlT9IZgEMdJ+xs2R7/iJNfYph7db26IPmWejo84DEn+yphb\nerd09puOsqzjV1SKBcIYj5gqOhHab5n1SS11mAA717vfLjBgOHiKZWfeCF1/\n/bJ34kmJ89jbtSejwYXKnaa/9xLlFUq5Nf2sYNiXjbRSgSWLUU8rSRf4aI5c\nDRjSbPnw7fzFIVX7rBMM6QcFNZHbuA9M73DekfyPHEMk5QO0Xj2JGYV2gKT9\nBs6K\r\n=iPXc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAXsFEoEYMIqx136/d37p265M2Auq1w9Cv9OrVY1zKTlAiEA9N4OUVqkAfyxJ04LQXuUJ+X2dmjbwbFLP/5NTVk2M2Q="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.86-beta.0_1591781583677_0.04838249506361758"},"_hasShrinkwrap":false},"0.12.87-alpha.0-sfcbasicfields":{"name":"teambition-sdk","version":"0.12.87-alpha.0-sfcbasicfields","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.87-alpha.0-sfcbasicfields","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-DwCZFplY4d8EcC+GZp7hs/nXpSFIHdWI/slOuOBK6Y9AiX0CjjiwdZuA2d6WIBYyDl7Dyz0ie1B87HAbYzKw7w==","shasum":"194f0919139148c41098a9d5f4959aa820d87e18","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.87-alpha.0-sfcbasicfields.tgz","fileCount":512,"unpackedSize":1060693,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe5x6oCRA9TVsSAnZWagAACnwP/2+TZ7ssu+inAhsH4d/j\nsi9r5aBTI3R1wSaAKhRXRzvrPeDZo3kS9QQ1w/9x5Fhe1jt+B/ZtZfhGJnOK\nwFO8ZI0L8yVqo6iBhIt6U1ZRPsB/7mgRl11+fnmuTGtC+A74w66CSgNv8jlp\nzSdYzyYUzzYrK2bGRwf81BeQjVQJpxyRO4Q4m0D3tKFd1EDK4kD0lrgCDl+0\nKffTla5N/8ekRLPxh8TRJUzRbOB2xBgOZOaL96jIet2ZqZ8N/ab5lgcUxiKh\nqjR4oa07TGZ7f/PnfQ8gPfC7XDgrJQ3m3nCauIaZWVsj7UGw4X8acbU5OV+G\n/kVUuL2tBHg/5pcmxhwhcoiZ8s4boreW233E6Tc8zqWGNVle4uf3gylIthbf\nO/PYaJlioEuyg5jHk8+aW2No3rIwj1/3EdjaM6zoUHVBC+iNo+TSiFSJaOc5\nH5G/RT9ZLnYN2vE485JYUQZ04OGrHvY/uwK6hAk3W9of3AYzvGJXksMnNPsD\nVf8a99hiTcF8d0lbckPH2sbRV1QaxhNlc6reIUQSlXBq7/ietM3roXUjcvKE\nlSLPLEI8QRIFyne2uD5Wfqobj8qtmAgAndnweFJgbXjEE20LNlXDkuc3JqgU\n02yK2VOjD9she8sYJk3cIKuQU0bFkfZbcLjD4DQhW+a9SJxTammM+y7e73+W\n0eGZ\r\n=NomA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICQN2Wf/Cvvwms0/TtNbzPc6y6EbxFoKxkxPTNffPIYYAiEA4KgoWgA2vrSBFvMCkdz80xEKpJ6zz9yBkAT4p5ibW4k="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.87-alpha.0-sfcbasicfields_1592204967729_0.6281272942494289"},"_hasShrinkwrap":false},"0.12.86":{"name":"teambition-sdk","version":"0.12.86","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.86","_nodeVersion":"10.21.0","_npmVersion":"6.14.4","dist":{"integrity":"sha512-+IVNykeNsZ0Y7o531iA2UEzZ69Y2rTcN2GAKN3EG/6tRccIWSIdsSoSEo1zGTQNB9Bz9eTFo5ccCjgHcvUXrkQ==","shasum":"0b6be00a6842f2421a9b68028715125cfc4b2a10","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.86.tgz","fileCount":515,"unpackedSize":1061082,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe6e0BCRA9TVsSAnZWagAAZ38P/0f648BnjAS1HtauRMiR\nNsbJ1Racw28Llq1K2RB0bly7Ic8TcIJ8y0Qv5LTquz1qzGSUqVhwqLsaqLIb\nxV6RjDSb3g5syDpDxEK+llPfj5gd90cpMjQfpsA/EbAtdpGI3UKPIbDnbO8X\njg9lnSqtcQrr6wcyHL8kPIqZmzJQDiM0kjMxqw6fD447qB4XTrUAc+wGNLho\nNdG6Y1xb4e5ZMWq1e0MhU0zxhsJ6UGOW1paU4T5jSNuuRenyB0evKtmg4VME\n0VGtkkZ6qxqlpv6OiiOXwGavOygpA6RJ3jmpSbDNgwQPfoDuEaXz+95W57ZJ\nr4EQWAAtRxQdC5OVREAG8/V88Dcjv3jwYqhx1H6lrmPoXwvEBjYPl9ytyjdi\ny9c36/Ggl/oPRWGRuYXQ0ZpYfZT7jUvf1Lf1TH+bJFBd4K4R1YxCKi7x6OCc\nJEw5X3YckzbkGQ5/+443VMXGma/UYuRUTQe4m9hsTgjKSACQI/MQyCoBjm2V\nTIK29orn9YeLWXq3X6B9LuXJg1SmpFAPTXXn3BquuVeCyNPAOoXLF2uCIAhn\nOOd8yVXhrMXNkAseFYhGrnVChNsPghxsLei3xXu9jKi9Bv6o/P2zoURJ6je4\niHbM1abk5STpqEcWG2M7lC9lk2P1SidtpRX3czv4KEfiCdypiIFlNT7PDmwm\nsDlJ\r\n=JEHg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDXzBEgxBWuMblxs/e8i6mUdQy0vpyR2C63ydfJfBUlYwIhAJtb8+Oqep/6ce7K+pUaTVaYyUsTNr5UPnSX3Ea8m0qH"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.86_1592388864790_0.23568019190640732"},"_hasShrinkwrap":false},"0.12.87-alpha.1-analytics":{"name":"teambition-sdk","version":"0.12.87-alpha.1-analytics","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.87-alpha.1-analytics","_nodeVersion":"10.16.3","_npmVersion":"6.13.1","dist":{"integrity":"sha512-dOOlI6QS0dqCKl3LCMKdoXSGnH74UUUIR4BrHCVBQRCCHeOT7tw27Eony9QNXYPFRuhJJfQhdhL02aer5n0KWg==","shasum":"7f8f7ec5c6bf8f89084e27eabf9595a2e832f016","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.87-alpha.1-analytics.tgz","fileCount":515,"unpackedSize":1062260,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8JItCRA9TVsSAnZWagAAM28P/3I0DF/LMtLEzuQVB2qA\nSG5ojhWK/DKHydtgkkBe3/kNJtT+OJjf0R9AAMqqgmu/8U1NCdkEiLca9DdK\nT58k5Yl/xo2MiwGvnnntTmtXmnZUpGCyKdTXAIkmVdGYGq0PA/8DfrJLFh1k\nZiJm0NgbORwRkAjs9+5fsNMD2eb1nxNQilKcH0lM/1kw0NMbIJJwfXeURVtQ\nroZn05xNx7TuXtKImMwbcKam8LgR9YVcHDq1KxmLbWp2bdl93uDiNQFcsRIu\nV5oYm1xU7jd3QTzXQdkGEaY5vuQpspy/eQSrSKOKgMMFyvhsXU9o5Eg9Ot0B\nmmzQNV0JD85Aw5dhWkqA8DQlcikzn77n4jGtDBdXc+7hyFgqBt3GyytTKtyp\n7FXVT+EqF0NSJGGXt4nVtyMhH4sIzftJZbP72QRMtX4zKWzCdA1QDcCoOgU4\nvPukbGdoR6B2UrVwsWRZK+3QokUbHYIYd8Deq3NLvmFMd5fxu7V12/8C30wr\nAIbkogI9ZbESw74DOyILbZVOIapAgDOmL8j+O0ydhouxpZfap5y+g0r/tb7J\nuBGx8VEPaFw1d2EH73pcmfWJqu2NW8a9O2Zm9zrWB5C2/KbXQ4021kcji+S5\nGvtpECmgmZu2TOUpvUUciJcqOBN3GOTabHt/bEj1haIaeaVXGHHBPPKlKHj/\nB8DR\r\n=BeM1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID8TkehhgarYm7ligfLO0XwM1eceZBMZ045PIkIUrD2+AiA6ThnSkZ/NX6ActImL4k8eaCLWVeAcJ5C7LYXat+TAmA=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"jinchang","email":"chang@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.87-alpha.1-analytics_1592824364611_0.45910314538696206"},"_hasShrinkwrap":false},"0.12.87-alpha.2-customfieldname":{"name":"teambition-sdk","version":"0.12.87-alpha.2-customfieldname","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.87-alpha.2-customfieldname","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-D97kybw15ZALpEGzveJfo85NSBx+W7NH5R/+88JuwnqhnSpcy/2gePlf19cvXTzJQogO6dOFAFnwphflbAEDiw==","shasum":"8a7a95e04b6d0eef0e573746dd8c13f033c56eee","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.87-alpha.2-customfieldname.tgz","fileCount":515,"unpackedSize":1061359,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8Yt5CRA9TVsSAnZWagAAGQMP/05xV8ft2gNr0t8X8w0v\nAWuZd/w0z98cmCtfmpsWM/xfwjauH7iKqOalL5rObdhLHoQ7yXYLtkNdq8NR\nUZTZrfftrxdWABrh1150X/64pK8B2an0IGiCqDRnoB/I2QdABWeW3QQmd9hL\nGz/62/pEZWON/OkIH5OkmF0aRuoQ5Wd6R6TrCCxeF8mntTQ/IpDy1V1LCLz7\nQIb1/h5EtTniAPcsvfWJNlRRX4TL+DLgh+DOMxKRqZcy8Bx3cn5gdxQJ2E7L\n+Q9n0vkz+yrfgM1X+6ipzPku0+NI9bLkOCcxBrMlWc92TLvB2pkX45qL1r6d\njFl2Y/CAKyNUc6Znu4RX+PcIgRi3/I0xl2L1zDwsQdrt/sPCuDK0LzM2f+m5\n29aDP0MDWDIsgHdBKTC+90ZSpBFhND70G5WGZOkOJlgtcOR6ELrNq7LTCMlF\nBki2duNRG1tiQcGeJOrz56AnqrcGEsH1DjoizkGvH9pe443EBqsOU94Xazjr\nbZYXBnx/bQa8/t9wFwREUbAoBhPvK+pLn4/1U3CCRO2ahLf+gwp/fkdt1F++\nZlLLB3od+TgVMbtFt7WNPTC+ieUF8Q5YMOwVvCnsM1tX4K9La61eduCoxnFp\nplQjWphqvw8aPec/hV/6ypi1YVTzIJJnXk5tlc7IuP0qm6CeBKNHvxZG+QJd\nX39s\r\n=/kBY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCmf1ygtjJXbJt4hGwT6MjmKdnxZiQTa5CJ0CUOy/57/AIgYto8S5SE3nN2oBhvjkcRCcrziAhrJFBh9DLGFbRSaJg="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.87-alpha.2-customfieldname_1592888184872_0.8359995359684076"},"_hasShrinkwrap":false},"0.12.87-alpha.3-orgplan":{"name":"teambition-sdk","version":"0.12.87-alpha.3-orgplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.87-alpha.3-orgplan","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-HLK2oKOjc7xGmq44oF1LA9hnJhPEnMiKX6bxCocSFWjo+M2DmNIVOF6Rdrd+lCM8KyuKRW1Gnk3KbEplOmWHEQ==","shasum":"cfc5f17fecc90ad28b60ce4267e0aa6a70cc183a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.87-alpha.3-orgplan.tgz","fileCount":515,"unpackedSize":1066038,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8spKCRA9TVsSAnZWagAAnNUP/jOPmlideHVFnSrgYzOU\nGTgiJqCV/z66pfi9lR1q5ZWemRnN7Xtl9BwplhXrNZAhfHRZV1XaQah7e21m\nXodp0dAlDjYHIYYmt4dY9cWsRMDIdvr2HWvOikFKgHPKCNCuhDJ4r1BiOQUG\nAZwCWa/v6h9OHQxc9UAeAhzV6Zu/7iot2xhYnWUZcHPZbf6Y1St3A19sIWkA\nKDX/04ClQfLLd/8NkG4srGy48lNOGhRnzhELcStbXBFW7o++MjmtqvRzK4O5\nNHE23j9EK1ta1U/6GYQU7aBSoxKqPowlEozo4aWvns8l8VzNPuMuwXqXLc9G\nmXCGTj07X0glnZzx2GPGpCOI9keXBJ8mNfH6hbPyNd/An0mST+yteLpWsHo5\nbwoHx1QjuZIwIFTef8Dtc/Ka860fUEKWK3cCqThhxM6UU/XBWHiMwgGyKbLq\nTPHmhjllLp8wAJh5NLa+Y5kjmdiLdkcwxDUeL8ybLxmKScnX/3TRpq+NbvwX\n24OuUPnwIdEYiKF56mRvNp/kYFHAlGuuov7hElZiDWUuvPp8WjpcjQevkH3F\nYPp7vA19/lVkM+j7C44Y18HOY1PG8l8yrUnSXjA0bUlJ0CQ/6TFfOYIR3m6A\nMrt4m4P8ojjFg8GzBFQDsEbtzuyzWYkYmHYSkSMtGqDOwqayN0mJvVU6O9jU\nlpA3\r\n=k9n0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD4ywVILRGCp9aihobyTh3lp5CXLfbzmJm9u+8bF8MzswIgGee2q9v52YSfSFIPRooTKEWvT2vJCWbyf7LO7/Ul7nE="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.87-alpha.3-orgplan_1592969801288_0.7057493633540186"},"_hasShrinkwrap":false},"0.12.87-beta.0-sfcbasicfields":{"name":"teambition-sdk","version":"0.12.87-beta.0-sfcbasicfields","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.87-beta.0-sfcbasicfields","_nodeVersion":"10.21.0","_npmVersion":"6.14.4","dist":{"integrity":"sha512-Zx2kuTba0TnMsqYsM5tgR1CLvzt2iwfozSDWIzrhzxMtHPTEidBYguQrxnbmOjqDEyq2ppN9VzgmjfOdpJVhqw==","shasum":"f567eb4d297629752e4368e6cf501126117afe17","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.87-beta.0-sfcbasicfields.tgz","fileCount":515,"unpackedSize":1065981,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8txRCRA9TVsSAnZWagAAWocP/j3kjXX4PouIDFqpEFgH\nofJG7f01nipjrDBj0UOjXv0VLf0eeWxGZ/AS8d4FN7SoRhstqKTaOe1ij4QP\nTLJBi8LUGtcik+N/4tXoA47ONIJru9dtkqCIjmGJnToOcCkGb8UcoT7Ve+7H\nTTngfW3f5Gzibdpqska4w3XhqYqjidZIfpDw94Pdd/0HVOI4agGuqWyJJS0Y\ndukycQ56EeyyTSKTxy8feccIHMf9vI54dWL784YFt1dNsisbtbeUf70KYveO\n46z8xD8fVJao51zR4phd4zHU+tIBDDTQZ1h+YDL4LuXzm7mWyi+UZE+vKkgG\ndKtwNigxDV0iSuT+4EoD8VaOcxUXv8FbHkHBy7PdACvOOYVhrkT4ulTm41u6\nKSUhuFuxcCAE610NnlPKLGeAA2lK0IvOZ4zPPlm5kdCo3b94GDJAmGQ8Nld4\nqq1Teec4Mh6vxBtse92djvJ5V9TzbmAu7O47xTQddAAeCsF9Gi04taVDyHEG\nLIY6hWO6BIOZv23Sodo4fdfpTFimer7mwk/HIhbnmo6LROKa4y0MTYhuYc6L\nj+jfOwNRhDaOrKdjinXAourymsA3E/uNrLc9FdmUI/4MAe4xiuOgmwXYII2V\nhixqUVAls019/rk9Imc/kmGxD1vPhel4wCWjCwgSb93D1QtgX5vE5I8k3AOu\nCcKQ\r\n=ssjy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDnwO7I8YAaA10pkOjLTrbpw9L27hTrwMd1ES70aPN76gIhAIW1rnIjnlNnMdUQGgvhLwWOGFxhrh9abjknmuXa2q7U"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.87-beta.0-sfcbasicfields_1592974417092_0.05902687605893431"},"_hasShrinkwrap":false},"0.12.87-beta.1-customfieldname":{"name":"teambition-sdk","version":"0.12.87-beta.1-customfieldname","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.87-beta.1-customfieldname","_nodeVersion":"10.21.0","_npmVersion":"6.14.4","dist":{"integrity":"sha512-y6Em4MQWcs9jxL53SmNUiqDWFCB2V2X5rM/9uLV+TtUuZHBBPrspFc1yxi3I/KFXMd69VjpE7/M2WzAEXSD4uQ==","shasum":"098169c6bfecf250f6e96730f2c7eaf37f301acf","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.87-beta.1-customfieldname.tgz","fileCount":515,"unpackedSize":1066235,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8ulfCRA9TVsSAnZWagAAVtIQAJ23P0tZUja7zHS59Ixk\nioAC6feE8M0TEXxhDsDBjV/JjDTLmfkrXwsA1XPSLpPW5W+inTlJRBnHWr3o\n3moRiLVyDOiugShVfLLM1UjjS67hREmPdFWWVsDfhIzeiiGcpbcSwdXxaV44\nCJSND1wzi54xIJnA1rFLcZsNwevzd7LJ/VCFV2E2D0eoZWGbS/Pz9iSquGUT\ncPQVzChx46LW2+oG0gyFBMG/oVdz4WEFyWwFmCTT8fQzbqP0V72CR+6DKl/u\nzD0u715Uy4xctRPju5KsJc7KUzF+zUyb+yDqtTC2+Qm3VQGmZPJp9peSQFjg\nNLnSPPbCuDPXwKRI40lBaLxYJjlXzMKf0VONKki8PhPFtIIXlsgf9y0Y6XCd\nFIJAt6IkqNkWVH+BSFNmv8B1Dsk4bXnKj5HsaWelkgzoUMRejhB/iGIVyX43\n3z+yqGeKgdMNK/ZaWlFQ9DOLd/O1uOu8BqJVs4pBsqmAy1iOGYNtVH/o9QS/\nq2Jia1j/CrG9VZXlPra2HpZa65l5pgGPJN69tG4b1IdIA8S+yBkxeHK5MBZi\n2V2jsAR94+V12uGAZrAYcrY6wLTL2uOtjtUyrHLus4PwE5usFdEQJTmtxd81\nhi+Z/XNR9YteC/qCEemptbrzbf1I/Oevz6aY3pA0HmTljppKV+QaOTxYGZaB\n9wgy\r\n=xA6S\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGiqobfmG6HY1mYVG25LT+7+XOFS5UvClUtAMNoeWRuMAiAPQiVqsjQ9FXm7OkyShhRIENudvr8Y5/BStHLctzwFBA=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.87-beta.1-customfieldname_1592977758589_0.7213398515970235"},"_hasShrinkwrap":false},"0.12.87-beta.2-analytics":{"name":"teambition-sdk","version":"0.12.87-beta.2-analytics","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.87-beta.2-analytics","_nodeVersion":"10.21.0","_npmVersion":"6.14.4","dist":{"integrity":"sha512-uwdiUDcFZFKTqN6QeZH98xX+FaBpcjAux3ngV4ifm6VFXVVxUyvBJJOPlXu/81pBDChkp0GEWkemhjOp4bsC0Q==","shasum":"884705243cb513871510587240daa5ebe92f4a06","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.87-beta.2-analytics.tgz","fileCount":515,"unpackedSize":1067389,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8urlCRA9TVsSAnZWagAAL8EP/2fyJ1C8HQtjUYhhlLEj\nEerR/dD+oqoHpaQ1472O/iQxwHFobQ1u12EpY7XD6T+6R5OuqrwOqs50lC0N\n2J+qJhsMzzruCZcFAGOivg+CMSWhxydw5POXxwOkEcye7sqMcmUJIJs6dtTS\nZbNEmv5fLERwuqVyZ5/IhT7eK0/4DCqwxqaHr2Z5yI/6+zawi8KEMPYuOlq9\n0NQOhplfbve7QgznnY/O57WMIflaV4V41cJHRg/DZwviQWfWtUNe11fI0j5E\nphleGLTOYPOwFT6Oso53L8RpqDAInqxE/vn+/XECJIi/JEvslZla1iPjhqi+\nYONXzXv92u7JBbpzgtoVVVArIvCSeFPGgPMajiX5JoIx8Ij9PCrQfRwmVg+l\nyg5SQbicGaxdlq61LWmoXY4qeutBx09wz+Qodm7whR21ovO18GydpWk9N6sF\nhi5UicmKVWkE551qDZu5zUDXK2mAn9QPOti7dOU2c6sQqmbrje6NRdUqByj9\nU1cz6zYwSxMcqCuhxiaEd1CwHM5UFkdlUUAKkh1bAPqj6/9BIlf1yPC2DgtG\nhELHf93OAwSmzIjXDU66r7iaA8WpJZGaWZpM5hj3M8h1E7r2uJ/zoKaiLCW1\nl46+0kY3ewJ1p8T652THkHdVDUS8MzFcF9Kel8sjhge9Hq/Y3SzD3sneVWhc\nbQwp\r\n=Tcfg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCyAZuTNmMNBbJmIOW4oaaa/sfic9yzOqaJgSraXHJWSQIgCXci7PGC+ix9aS+m0eBHJbcc9JZtZNi5aoow0wq+EVM="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.87-beta.2-analytics_1592978148578_0.3881010818225219"},"_hasShrinkwrap":false},"0.12.87-beta.3-analytics":{"name":"teambition-sdk","version":"0.12.87-beta.3-analytics","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.87-beta.3-analytics","_nodeVersion":"10.21.0","_npmVersion":"6.14.4","dist":{"integrity":"sha512-7SHczFZYT0DQM46LxLKzgvIo9P7k+Be/HBUmWDRkNxhGBRNCBAsqQB2M/PPYS/K3oX732gIKJCpXFShK0EAh8w==","shasum":"e0f2345341b5549a572fbbae0b48ce2d15590719","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.87-beta.3-analytics.tgz","fileCount":515,"unpackedSize":1067608,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe+vMsCRA9TVsSAnZWagAA2gQP/AiM4+3O2TzQsgzDwifL\nQuxKMnRalDqWtUwVTWl7Ww9PWztNdnJLeEkLYLAofP0/ciLBrMaBidb+ob3P\nXRng5Qqq8TpMlMlAopSwxrcjSs6XiuGzxAvopNG9dOlsBIsismOVTE7kAJYd\nHIprIpdInPU3XZtyb7DIEkj9+xhB7fy/Mtmy8n8IxrHOPGZ54Wl9ZBTIFXkL\ntIc5O7TT1x39LZ3n4lmTWFzxtCkFSl29IaevxpzpzBXqQRbMfWIcHNJyxW3O\nht+uyUnF5KpKn+CgLZ7PXfey0hJkx6FSgFm0x9dbQjA6yNvgVk48wPHQx0o1\nX9RtVKXIghBrczgxJYuSWru8z0ZiPyjSjEsDNs15jL3grsjJIxWmbJ1UJMxa\nB4U1CkccLTZzpddkdnc8jxGilu4phZOcxr3z8gDRgsse6geH1blQMeOsAUXy\n5K+ilJTqrLjo26rBny6M0pfO1gZ0z2sbSw1DlGxjUTJAFQs07wLqJ9ZCq4zf\nAEXwTau6yCwR754918FCJh2iA2h5eiD3pW+X7xnixDToa7JSTVP5Sfy7WevU\nBeJ+sEpGwXE0eNhTdP3502xcfzYzYrwjourLN05IBh7b4d0Y/Apo2lycAQUh\nNWxH6Y8wGomp32wAmptKQF+qTc0wkrCcKnAfoSHpRa03f7Ka7K6DmI8aqjOk\nmJs9\r\n=P39F\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCOrbTSZW98K/YYHj9gCRBfROKDog/9ddaLO/2MNgZIbwIgBLw/5fk7BfknwWfpa9BSqr7tIDc5aTBjl3zCLv2WSy8="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.87-beta.3-analytics_1593504555173_0.487004163925723"},"_hasShrinkwrap":false},"0.12.88-alpha.0-orgplan":{"name":"teambition-sdk","version":"0.12.88-alpha.0-orgplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.88-alpha.0-orgplan","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-NRiJPXOnGXpzeRASscpyst8XVkkplIv6jZJh3+lJC5QWyONachzuUjaWt45KtXcfLn4hUhUWXidkgeSIA3G6Tg==","shasum":"b64a7aac90d6449e5f7bad57adc2cfcaa7b378c8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.88-alpha.0-orgplan.tgz","fileCount":515,"unpackedSize":1072328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe/CKYCRA9TVsSAnZWagAAVFoP/2+CtTPCW+Zy5OsPv3RW\nEXyAmrcxGblFZWkQ97nHncymUt0ls8ECM5vF2YVlXH1gh719ivSC6VFEIJZL\no4t7hXLYkaoCbH8S2HE7peiRI/vNlvJ+CSHf5zd/algXdvZ+upuUAHGKPXe2\n3UFUX/SauuBRMw/soi/9Wyleu6UBpNPthb4KVuLNP16z9ERZKgSYni/dVpGV\nSx41Fu3mhbLNAMT5ybmZmq0ks3qomLtvz3m13gs4zk9uhE+qKqdfhNj/rySL\nqSx44OiAmO6oGwi+vObdidVj3pB0sTvKOd2VSZZGs2rEjxDPCM6cMk5pi1zl\n8QU7TxhdvWnbyMWMReLklafGPzkcBFMifeEiKBCgYkW6/H7TV+IISpJJPCNT\n1facrpQFQ8WNkxRQ5fDo7x+hPM+Z0MFggI1xMGfUSYEDOdqOw0WoGPYSpLY7\nR+tiPFrEJ9OgpDRLtH+ot0tJ+AuIFF9Jfs/t5FqIxk6guapZIZHyw1dHsbev\nv8yksxOEpk9Vhf3JP9xVaSJksrjHhjSjf88ehMlbpQZlHyPr5YhinCFJul4r\n+YAOgI5O/W7Qq4v2UzX0lTrYDqmY7rBezAz2OOsm6tvxpYntz0UqHHhPY/Hz\nTNz4LleJbjDnYPHUgkorwxHmxx8d6+zJEF/j68/6q5pHLC5ox6zmtydIIU+e\n2cF5\r\n=sFoH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAdiyeBcs8BpaRsLk6NO6EppyuqrcG5rMSU55r3aAQWwAiBXpg9uR/XaN6vZltgOGSbVL07qb4FXApCF2sDj05DsgA=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.88-alpha.0-orgplan_1593582232225_0.7040477880834799"},"_hasShrinkwrap":false},"0.12.88-alpha.1-orgplan":{"name":"teambition-sdk","version":"0.12.88-alpha.1-orgplan","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.88-alpha.1-orgplan","_nodeVersion":"10.16.0","_npmVersion":"6.13.7","dist":{"integrity":"sha512-DiF15b4M9LaTBnKXHvmdPumf98T2N03xehEmWQh0rIKIuvXWIXwL70Q83o68FAfxGjUuPLZZkOksqWiNaZb/VQ==","shasum":"587623ca43ddea068484cf5c6cd17c3fafb2f3a4","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.88-alpha.1-orgplan.tgz","fileCount":515,"unpackedSize":1072547,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe/fCsCRA9TVsSAnZWagAAifkQAJQ+RUX9MyA1Nx62FalK\n2yWTD1GbqByEbqUKW5j9oFUJCtOXS/WtstByuvpxOosK/NntezRgUVYvMJhm\nT779XaEt/zg9O/xs9X+5pH2yDp9IVPS2dE+q9//wf5asMiMoSOAmYibck4sJ\nPphxSltd8ismxSQvt5ln8qvM+Nqiq5X6U2kdvoMTQkG1Bzr+sp7VrfSXmsaw\n9HwLromesvM2YqTXNpwlBEI3/iAqEir5R1m9RyKqgi8sWO+Y/wZDgGwAoRAp\nBd6pEnoL4nNiJuB4m2RkxiFR1FxQUO0swpD08TBMo82Ac1jKrAySpDHAGFcz\nx19UrggFYeMmwnsSkuXvsF90XpvpMeiPWQ7CFERvhv4YpTSPNEkk62kxE7Tb\nzG11yNYY+B3Ny9D0VVi3z2b/D2/oW16+T1UkvzRk8jQ3C6h0OGXj7sgrsqlu\nO4HbNOCPidkeggvkoq9Vi2ZrDRmSQ0qNhVijooEgd3+UBwwMkh8Fr+hm4PhH\nf8/Vtl7uESzvzMGBu/RgBF5w2f66BmLTq75tavl9fi0Q5+UyiwgP3G3z/eIz\n5E5VFXov3V4cAGHfH1kzWW8xVY9HMy4Hat5vWjcCITPEaFlckvgJ/yIaswtN\nwWlEQMS10WSK/RHX6uFPWOkOWeD4jy/R0fk7XF59e4Q/Fq3qQ/iw82IOnR5s\nK/5U\r\n=Rf15\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDEO9S6M06S0lLwGeLRZ7J5XigCWZGNKj/JXJRbm/MvfAIhAK3IoIn3DPqambmWFYmO2J8cD+x+ClBN0CEEVqwlLQTr"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"aicest","email":"aicest@users.noreply.github.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.88-alpha.1-orgplan_1593700523640_0.4341575268957454"},"_hasShrinkwrap":false},"0.12.87":{"name":"teambition-sdk","version":"0.12.87","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.87","_nodeVersion":"10.21.0","_npmVersion":"6.14.4","dist":{"integrity":"sha512-TfiY3h9uIwS/X0mz2MQXG5LJRnBrlDTchbftLP1J64My2sTLptaJtSnrMkWJbApz7OdIaESZ55tnAj6a3Ts/Eg==","shasum":"3797436bfc9912ba29a0869ec7a7b8b0b1c8a798","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.87.tgz","fileCount":515,"unpackedSize":1067871,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfA+XuCRA9TVsSAnZWagAAP80QAIjWjBKuGsPAiIpyaP9d\nFz5DVpONtd4a/xHzKSbsTI6ZlkVa9gRblpH9XbUeSxMOyk02eqeXalGpJCA7\nFXiswxaUPqSsvj0DAU5oisFs/2y378w+2m0Djhp2ek2P6IxLNHNx+cDwXbV/\nEdpMmazs3TM7iBM+0FbxPd841rifTetilEEyKG7tXn0Fo77oWt2ACCceXy+b\n0P8FEgd00ufRoahJoz/hRYSXIoahEw2I/me9IJaasuoC/tcCBNXYxLGR9IoX\no05euSu7e4c0NOkIdGFdMSoiVkDQjBS57fjrCIZPK/TEaKMgmYd426zvCSAf\nQwpduLkWRFdFhxfaZ1pdz/tz+nAXRDJUNplAmmHxMN05ozre36KqtR/IJeOA\nj8mS3BbPYlLNPW4dIAFSJymxr8IUwOgs3ZeNBRJvw0ss2jobcPqVNB9loCNn\n/T2WLoBdw42rV/oYuGQg+gY8WvmLLDIPCixyd/a7O+I16RT6l4YjO0Lun0Zr\nTquLxDZNEJ9Atr3MLx6y7sf905riPO/v27taURp8Bp5UkFV3ZVTWjzX8YPWc\nhDUFuc/JkqRfFlamuU0//zVqyCm9YLlf7K19Xe4RQFh3Tb+KYRJQSzF7eZ/l\nBOAQynWCO1brBDcOv9v8N46MnB1Ktps/9nR32FFAuxLqjqrMoFTsMtBA72X5\n5Smq\r\n=Fhyx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFiCs1Zi4ooz9fJ/6sjBtaUDvNpwKI4l6zid3x5Uj5naAiEA+2XeZMu5xK3bMoLYB0SRl5sYTOwjfRZfmdJP0PLZp5w="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.87_1594090989485_0.6459506382426301"},"_hasShrinkwrap":false},"0.12.87-alpha.0-personalorg":{"name":"teambition-sdk","version":"0.12.87-alpha.0-personalorg","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","gitHead":"7489510d0d5559a20afa5a681129bbb4eaf09e69","_id":"teambition-sdk@0.12.87-alpha.0-personalorg","_nodeVersion":"10.16.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-co310ursRpmIpq7vtiDhkCEv5a22Y1n2IIl7V9btHm+5D3R1TgEAE5RZDiVAffxhMuUaTmqHB2L1KdY8nqK5hQ==","shasum":"bb7e6e9f44650196e3fa43a8a73f9d9c2d200859","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.87-alpha.0-personalorg.tgz","fileCount":264,"unpackedSize":908876,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfJCyrCRA9TVsSAnZWagAATrMP/2NeJHZ4LUbw3cSfV11e\nNVRcGmzvb6sglFzVEv6SQs8+nRNNbJlcXF4BdMIGuu6RU67yeCFQSqGf9qKG\nK53R7Yu3EvZuHAa9/btqosxYqFf8YLnIBanGy1q2coZtpJk4pcH27nE5go2T\nqF7C7uRSrp6ySmaM5JVr20v38TLRgu8YYTExTGldOGG9FohKGpqG2RX5I6hf\nl9vgDxyb158hFjoGaIBW/D+3ZdiFSQJ70z1lF6mufQibE+0c/ElyNJNrx9k7\njPWWjpFsLnJA/Wm3lATEZrSayRCXLGvReo0SQ8AUFblbYn3ymSrLDCIh5wvh\n0bwr73VAaILbqxhnycCM3IzptGpLYFJle9tw4A0kIJP984/xi78c/ptiRZSJ\nPtZbhG/kOv/37HCeZKgEGJye7/e9+0oXY0mNppU2LlMc+CEo5O4RfZXT0Xla\nfBhgM7fJWt+phqw22DxEM8yHb51jxfZ08O5aVr2mLHz4DUmkEuEVqFRsNinn\n7Z4wYiIn50I3iFyTEthYZnauvD3OVudqsT+1qj7R18jOZ7Yu56QqULsg/Rmb\ns4f+/HxX4XK13FZu2bGP6j5AiwR/hSJx2Rep3zJy9ZACIc0lM+qyT9lnxmLG\nX3uEmqSgnGlDch/JJbHKWynX/rIXyU0hYOM+4lhApjgO6xklvI01jgoQhv4z\ngZz4\r\n=wT3C\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEa385MqvEmP0Q9gqEy+5t2O6+zzdVw/Z0bBwEu6KdZrAiAs94lUSGMvZI/VIjZFY6Gp2pK69nytp37Wqvn4s7LgEw=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.87-alpha.0-personalorg_1596206250379_0.7427686313497162"},"_hasShrinkwrap":false},"0.12.87-alpha.1-personalorg":{"name":"teambition-sdk","version":"0.12.87-alpha.1-personalorg","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.87-alpha.1-personalorg","_nodeVersion":"10.16.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-f7Nv4leKUbDyVckjy1SZKbjuvB27jsuysC3mdT4siEKQgbXZCuXZYsZtd3xJa+hQPDi+OE5v4o2NLEPE2IgMiA==","shasum":"61107b524b050f66d927b4eb926f64d6b734242a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.87-alpha.1-personalorg.tgz","fileCount":515,"unpackedSize":1068261,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfJ8t7CRA9TVsSAnZWagAAC3AQAJKpTebj0gNSYCsYTgee\nBhqOHUQKouqU95uoTZPnDQBr0rD2e/LC/cNNhzeasrvUOhcmE4fCDJSIyNoP\nTZg/ErHsGDxR/xJVt/92itk/5SK2pmKxUg0AHa3ub4dPil2WuMxkkSGEWUwQ\nhs6Nm1VK7/PXcCQPdCz0KxDUzMYapPMFVwRlZ2/76GpXOn9MS9WE/+K4Y11I\nF2RMEe/VCoQY9g3zjPKEgkRRUPVEL2FCUBfPBmwYi5dE59TaWuifpPcDFaqI\nEhTRLGxISrWBQrFrvjPu1eogWaQQ0zfCfvF1BbAt1XOgWswq5exfEjp+/Uy0\nXGP+EDKoNVcVEx56bXZfZKHCpIQmUcI7v4NsSfaiSvRhOQRy5QTZSvkJ8TWz\ngBO4kb4sncjA+Dn7tlA2ZxxEwLqtpBMK+N1RZCiveo1zkpv4/2y5sACr1wVe\nF0gamJce070gFUb1y27JK14YVqUN3kNvD17UH78MTb7vRfWcHFZUDfYlLn9j\n63Y4cmYbxcAgjAVHstUSDuUDTtJ4bjfRYWLacimcFokeLlH9pnryYnE4TA2m\nY7XjCk+hplMlTBe0iMMzd1FrNvmmAHkBkhhNUFTsLvPl+cUxqm3JUpWr8FoC\nu50y7w+NgyxF+LS93hjq7/GCPa+YtLxNkNX3oCFra+JY81Z2tUUmOJnyQ9ak\nuisD\r\n=d4sk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC0KYTMHyhGNRMYq7tP5/Iu64P860s/n6KKaVDO8da6swIhAIVU7MKvKZhQgdujGatoPdZwwwuWIKRlZ7Qd9UNcPDva"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.87-alpha.1-personalorg_1596443514624_0.6004834276423467"},"_hasShrinkwrap":false},"0.12.87-alpha.1-projectreminder":{"name":"teambition-sdk","version":"0.12.87-alpha.1-projectreminder","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.87-alpha.1-projectreminder","_nodeVersion":"10.16.3","_npmVersion":"6.13.1","dist":{"integrity":"sha512-8wBrW8lL7B21sIwT2p9hzsNrUUhfX/viZ7j3xJrs5UI6FH29kwa2B/R9/0fxVIrP5UuTAHhgMCqQoz17xjFDxA==","shasum":"361dbb1bfdd50cf46f79e38b5ab20b1b8730a02f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.87-alpha.1-projectreminder.tgz","fileCount":515,"unpackedSize":1068250,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfK8CmCRA9TVsSAnZWagAAOXIP/2Qd36WVIl2OGU2oNwjF\nKMRFmNAREAYwdtWRwItwDdqLFPW6tTp27ajFW84LrgnqDnNGS3zPWChEIcw4\nUCC0xqtEmuzEbrbVL/ZxNbin8dH7VoeySVA+kjFGgyCZ/CLeD0NdHMJOxwWx\nf32KPChGMbIs/s/HUgrvD+TtDj1g0Dct7WmdCcEzrmrCG0jDDJFGSzdqi4zm\nXvoEzC36ReDAFtotPnFzOGZ4tS80MKPytsmH5sVAJXH/iuj8KJIER8CG1HJl\nrf11nJcuNrqe7gUy4ogZgNdH6s/vBqFVvAhd98v4gUY1UDyRhusLJygf3M+E\npY44pblQ/pmPDKh3xo4WnXkWjeblGP2r2Nnt94pQP8jfeXNa/R97zYpFW271\nIkBLvB8SLeg6s2NlYlfaA9WRcn0ulBKtLKVod7j4fFOiE8kZsIq13Av+TPaD\nhHfFJ4nkd8FQdTRZTiV0QBmPJeMmRcIm7bkB02TOE1S6ntKwJYG6Tu2NvDFW\n9rpYdu8La3jlY+BWIlSNIiyBaZiQm91yOknS9sfVO16wCchk6oSqMmIGT2Zl\nwnJUBybopxu8wvYan7lOrZG9cE3A+vK7m4UCGGkx+BLeg5lDTBjuDCST7P+N\nk4zCct3gyMtGoxX//Me40e1VzgmtazG/ZfRHSYwzW0UCHerAjNDOOHcq8XOi\npTN3\r\n=nbC/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAb7q9K1Vn94Jj+NoBjS6muoWaqS33QiazpW8+OQosvFAiBOclLr71Ec3ohMTEcAq8s8wm9vg4mR7byt8onlik2b+A=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"jinchang","email":"chang@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.87-alpha.1-projectreminder_1596702885490_0.12107027336407183"},"_hasShrinkwrap":false},"0.12.88":{"name":"teambition-sdk","version":"0.12.88","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.88","_nodeVersion":"10.16.3","_npmVersion":"6.13.1","dist":{"integrity":"sha512-no+qTKwzAu4t1XLbPU0oztcXQcJxItKeQHTQEh8EHF7OmaXN09lMRGu8QQOl25Ao01m/LrHwsztDrWSPVs3Wkg==","shasum":"6e8e154a95259191a14bceacaf904352892c7972","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.88.tgz","fileCount":515,"unpackedSize":1068226,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfLNq+CRA9TVsSAnZWagAAQgcP/3iSewULwlqBHy1+Ob97\nYaLrDf4QEuJ1TpSJqkGRK+H0rv59+9iuH8AOcBxDv8D4Y34VLUzj0KkqDTxt\n258sVRWtUoTqsdlJTwEqrXLDdCSNNlMtse8NQsV92EQMhjnovPwiHXadmXnm\n5dMI2CyLnI6MtIGatJKtkZrB4k7+xSfbBtezDfPU2mpKTLcngPZjM4qBKRxI\n+wLGJLYJ+fPIghbJZjlMSnx8/oqKfnepEkPOz/ZKpaLAaN28KjVigoYllZYz\n2t3FgSQXwELcBz5qJw8Py1cpk9b5Srg7YjKlcRAQumfatROT8Ge4iEnLRtev\n2m5of5xGYQWtRcdxIbmGdwrEvX6xqizNyA/Wj3MBebKG4NXt3eQByXsxygVJ\nMBNG96o2jOwT9I2vGaukL09BcA5akq7+ozT85fOT7cfoH6MSgLz1Gy5NLp8X\nOJ26+h2Hsx41XSErWAqOYfPizMZi1KE6lFZ64A8hYwQAVC6zHfq+TTCmylMA\n6dL6RFBZn9LJv3FyaHMCxR01lde3xHDhPw5WkQnjONzXAr9yVmQ//kqFRXdb\n2rQ26YIHrUlZSIB+9EK+4DfmVB7e1dVpAmMDnReHExpUuiBWAXEdswjkO3EF\ngiEP4Vi30GyCM9TUIkV+0MELsT+KdRaKlpH2ncv8YfJDNCd0YZepagNBO6gt\naMyI\r\n=SyZU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCHwZRdd+cK3lSkE1SNwA9M+AcwLfGT24JjKDa+h9IvgwCIQCiOG5xnBtrkS6NOd4P7/SG2l6iXey9KTt3Dy3j2POfvQ=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"jinchang","email":"chang@teambition.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.88_1596775102133_0.8018641539501781"},"_hasShrinkwrap":false},"0.12.89":{"name":"teambition-sdk","version":"0.12.89","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.89","_nodeVersion":"10.16.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-WaTsmSTGRMlFG9+psw37YpfAuVhObSydNHzyp1EuiUgaBRcCP+sx95i7osPTYRs2+WOrpgSUpMfeWp8roEuzxQ==","shasum":"22fd3284e0fa80dbe81cadb4a0baf537b9484f99","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.89.tgz","fileCount":515,"unpackedSize":1068596,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfLR60CRA9TVsSAnZWagAA6ekP/Auojiaf1K1l3mJXIIg4\nqD5Q/92kJUl7aSUXevDcMYCAY8UP8enwuCaMUF5mkhtAfYlROcJevDl68GDg\nz5MOqSfzmX7GDuR+OiTnZDeFnd4z8IAus3lKZg0Rk4MGu03Asvrq+PrNr4z8\nefMpBAjFE4n426tHT6rPl9pulFr4OAYAkQJ7nrsEQwf5sxLW8gOJjpqrRpsj\nliBxhvAspVLh/RmgzMtAmbfuRadjY7VFN0aAAhIiLkq1bni0SYeDISSPyMo2\nnDvmGWTXdpjPp4sxwqgwkkafbF0B6UFCpUKKpTHLb0IreDegZ6pOudE7GRN4\nASzuFRVMNOgt5rlbim9flsPihEuHJSQi4dUPuMncE8xX2T2cqBJmmLw4Q5WM\nRw2zui5OSHe+kW3TeRB0C8i2bnXNx8Kieb1b83Xb2/7Y7lgKY/Y4cpSGJUdP\n3kEI+YHl04jq3WUkFV3oGH5CmDUWWpTqmvvh8zSyn6aaTcE81JHxdwzpTr8w\nVlVA5Hp6YQUIY4MtujfivBd+dJlyeIO8RVX+j3Mh8X5N7tXmu5pmbzSYJAlF\nNtb6FxZ2307F0ikdGLDXI5mX905WqlfAmqqD94TAimGsMK7fGj8Wrng0MSmW\nXD4TtizuvnHCCSh+iu97pkjBxf/P2iHeaKrh5YGiD/mifxJTTiH4wLChnjqG\nG1VG\r\n=SyGQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBM+Iz/S15zYlDApfvdcKfprvfPzbaX6QtdZqC14JP1/AiBWmhl2F9UH8IwbmdtWx3N73oe2I4y41/jvTnU3fAggzQ=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.89_1596792499862_0.6551800358926669"},"_hasShrinkwrap":false},"0.12.89-alpha.0-kanbanconfig":{"name":"teambition-sdk","version":"0.12.89-alpha.0-kanbanconfig","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","gitHead":"1dac0bac2bcd7433829319b829d45cb5cbf1e860","_id":"teambition-sdk@0.12.89-alpha.0-kanbanconfig","_nodeVersion":"10.22.0","_npmVersion":"6.14.6","dist":{"integrity":"sha512-9UlXAiemm3vCo8CQr5jOUs4rMJtjbQjMo8ej0OF95Jx5hAlYAKz2FxogSIfYZCqEKkFjBl/nvoqzr1cGIvUuQA==","shasum":"32761df1b4625cb713f656ff414349ef3611b8ae","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.89-alpha.0-kanbanconfig.tgz","fileCount":264,"unpackedSize":910404,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfTbaHCRA9TVsSAnZWagAAmxMQAIaF1oLk7kZpXon6CiOi\nrQ14JaFMja9rUw2DhBb1wAvlUKuM+137NaM1aJC5UtN43Yd5kUtGgyq6vI6T\nfsKGZjD2ourF3C4lMtXGxTN1T821M4UP53nf33/57vzhVRPtlmuqt6vbrLpY\nIlMyTDyXwy/gHBy9nJ428jaUmFd7xVhuvUnQT8VPGy/40czkL+SV3R69sLXZ\nGbX+AICJXOhQjvzMT2YdHE1taRr7u8lQH2ydmbBAhe4RzCZHIdKBPL6pcAG0\nyUT74zoOYfEXU1eAbG14I4GQREmcU19EhohoERCHSuM2rIG0s9EN1Ly/dgf5\nCaS4Bd9XDYWQHKsnCOWC1E4cV5vRav462k+Q39ilAM/EjG7ub554iCLbYTqt\nU6YbxtOhMqdsXelTLW4fzFxLBJWKszpyaaVanYfacfWXWCBrmjbBcgDBcyFA\n1Puprs/VTybM+lo/YOMqvUhlkVollsnCetvGRits62O93QWWIrnP6sbnZDeW\nlgtk2AG0O+DsosODobmpp5PEuOXCvIDc8KTqkrysgKKj0NbZLEFx4bQly/5d\nr9i+k4eWGWihi9ZCPEce/Mt0k8b5QhjE0RLl1AoFQRMn6mRrQECRq1yFP3rr\nyHOpuM4cX8SudNNltSCgVtblhkaL2+hTymkYdzzZH9Qh3SQL9uBT0e08kDH1\n+FVQ\r\n=9G7W\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDhqX61tZpvrnWD8yxYNamgsR5aI0QblUbTd6RjaRhi1AIhALbQP0bB6qKKNl/P+InX+yIAMXg+urrBHmzW8l8ouDvY"}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.89-alpha.0-kanbanconfig_1598928518867_0.7659096843986439"},"_hasShrinkwrap":false},"0.12.89-alpha.1-kanbanconfig":{"name":"teambition-sdk","version":"0.12.89-alpha.1-kanbanconfig","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.89-alpha.1-kanbanconfig","_nodeVersion":"10.22.0","_npmVersion":"6.14.6","dist":{"integrity":"sha512-mb/meT4J6f5D599dBgJjld1kNbDWzHPRCOAPwaJACkhs69ZSg89a80IReriFr3jDXoxZd6KXvylgMgxhH/Ob0w==","shasum":"cdd91b6868d902c881c3fe7e831af2fd3006fd81","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.89-alpha.1-kanbanconfig.tgz","fileCount":515,"unpackedSize":1068617,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfTbqwCRA9TVsSAnZWagAAGVQP/jJfF5PgZwwZ2vxTSylp\nTJBkNYjcpJFxW4691aNdD0HTcr6/wFrGlb+6LKMnNHD5V7BHvr9XI6ME//gS\nhvWL9ZBAE545WAAm42aBVY6emv8ptMv+DJisobzmF+lUKfZuFXdMqJraSZan\ncK11/ZVo1VZIgNeZEY1uqjlwVRCF2dAseVFYkNUxqFdtAqOvXpJwcoZJvdyG\nTX08wXPAcvVBu3c0qxx4+5awb3w9/e2F2iM+wOs01zAQFrjYns5RooplkXlZ\nlYNVBSdzDzqVFo4MY0t1HKG92HQ50bwRDUWl5lDhog+L+AzwXFYY8gQxclPR\nGlCozr8kFrt0buMKGW9iGmceXxTI+e+b4RAHGggroYMwJ6DOfyXsboXu/aAE\nDqWj5VaHA8uWnCyXMvt604/UD3cKH4oL5ggTgaTohK+k/sxBsHrYckJcnLKC\nLWtiZO8uq2f4DBRKKWjIFMeLElozYyXIaVavgUE+PVPH5MWWWzc6VLcT5xRj\nFM5al0q4LhG4gKzGx/ScK/e8g/yxIyxsU3DrDnTqfgcJdAyYKDi8tQzTWKBm\nxx8RXC992OkeCIiPxNCXr3nAifX1+aIwIDCn71y2ZhLz2l7TDUjS0UBi30Jv\nMEVsF6RkDIB6eP0M8hwxO2oxZqJB3YGU5kudDb4Me+lpYH9Ii8mJNVC57g/d\nf/IJ\r\n=J/Qm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHxNoYxkZNTahHpPB3JqCqX7GpP2HBtLPpSXZTB6dGDQAiApOmfHtTHiFqWepm21VylfKGEMX7V5ubJa3IQa1JIYjg=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.89-alpha.1-kanbanconfig_1598929583491_0.09330611836210467"},"_hasShrinkwrap":false},"0.12.89-alpha.2-kanbanconfig":{"name":"teambition-sdk","version":"0.12.89-alpha.2-kanbanconfig","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.89-alpha.2-kanbanconfig","_nodeVersion":"10.22.0","_npmVersion":"6.14.6","dist":{"integrity":"sha512-khh8J0NQo5futwbhTT3mG6oHGaR5UAvVQcTAa3tx7Pa4SGOGV2IoAzQGbJTZlli9NEAea6urcjD4OK0gEg6kyA==","shasum":"34f69db50407037a0c046642a0301e767162621d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.89-alpha.2-kanbanconfig.tgz","fileCount":518,"unpackedSize":1072938,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfTb5OCRA9TVsSAnZWagAAHM4P/ijcBZYBlKIMWOzlCzNa\nXR0z+MDrzJlqPazfrIkVqMcFlYJFJQ0FMl0Gs5R1nKOA3ATETVlsaRudPgjQ\nkhQPrGC+gp0aYLDUCAq3491XU58R5rEPKeuziqpIp5vWRfr0dfMqxTOJTtW/\n/brleFFU1OfkFlkwKr+W64n/di88M++4LsVebokkImHnq3L1LKTIlCY6mdQ/\nVcrgOB2cXE4oEDViSK1cahsI8KPAZSUJH+mo3LGIc+VcYTu1kGhcOYlyA4dJ\nF+p/+n0LQ+x7WSrG4SBqDPLN/B94x8mlv+2lIHBXc33bqlFxSfFSZ8fwb1fe\nyj9Ymyd2TiutEGXcvj2TfqIxQx5YQAk+VyDKZS6NNxR0DoXmJRkrWJVYyoCr\np9AXX71+XV9O7CAQRGfMFpVgREB2uFUeQdei2+ca27e4jiLw+auVIx8TNj8D\n2BHDPCC8egz9SRaw4gf60EJjItjCdNAeJTqZISdMcc+MmLatS3LdTGZEn8q7\nmQNlbvOhZmnvtxKgTEpCdmzYIZBh5BCYiVrVYz58BPXhZK9uXs9vyQs4yPbC\nIAzieuhKrCWob3itdjXl6qylb7bzYEV5QKLL2mQviYCqjfCKy+R0wbX2dHmT\nG7jxcwIin75Zxe/fAGDpmeP38GotJK57wgq0KMgKgiH6xfMiE9/B4JNisXz9\nVaMP\r\n=R2Cy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDl89KZQpDdGkKW5mIG722QWwpAeAPzZofKWOUEZufmWAiAcA+OV7eoA0KUSQf8hEJ4dnemj6r33qUzW3DkhFfcdkg=="}]},"maintainers":[{"email":"zzh209519@alibaba-inc.com","name":"2ehao"},{"email":"aicest@users.noreply.github.com","name":"aicest"},{"email":"bjminhuang@gmail.com","name":"bjmin"},{"email":"lynweklm@gmail.com","name":"broooooklyn"},{"email":"chuan6.dev@gmail.com","name":"chuan6"},{"email":"xiaoqiaoqiao520@gmail.com","name":"coldfannn"},{"email":"irinakk@hotmail.com","name":"irinakk"},{"email":"genesis.null@gmail.com","name":"miloas"},{"email":"ratsunny@gmail.com","name":"nekolabs"},{"email":"sirius0x9@gmail.com","name":"saviio"},{"email":"web@teambition.com","name":"tb-web"}],"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.89-alpha.2-kanbanconfig_1598930509656_0.6892643291927187"},"_hasShrinkwrap":false},"0.12.90-alpha.0-analytics":{"name":"teambition-sdk","version":"0.12.90-alpha.0-analytics","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.90-alpha.0-analytics","_nodeVersion":"10.22.0","_npmVersion":"6.14.6","dist":{"integrity":"sha512-00kBRazBfERxqzj7OUM3m8jIA10k31p9hIKkkhEegv8FF9AgXMzaQ7BLZmYw9obB1aIlJUbnfdta+ZG78Gha3w==","shasum":"037424bb6b3189fcd3a4e2de81b4b9f56f0ee3fb","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.90-alpha.0-analytics.tgz","fileCount":515,"unpackedSize":1068687,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfVuqmCRA9TVsSAnZWagAAxSAP/2QBk65wS1CPEy6EQiGH\nIdPf1JdTaDcCpgjA6SFVXk+k2Vl73rdZO+JMN8YipJ+gcCYY38wchjqzkNFf\nLLJhywabw30p+HPHwXMeyshjMkgSK4auyAYRvE78rScYN31s+JA93zA9nBd+\nXuN9S7gZ4jjpD3gfKm5jL/bbZkcra9Mg37GxhLybquQtsOJaAkiuon6Hzuyi\n/iJ00nXDVwAP44Gv8/7x5uxV5nS8sLZBZArxt4W+RkZK/ec6kWfYtz3amozR\nqc0VntPsbz1hKp6kIqBasenF4AAschWyvEFY5rYOpWIzioJi3yShGlj7ALWB\nKh7m4kiJckS094riApj/HQszXbcnmlfawB9ywy2MipZFG3wx45Evn6gwmdQQ\nZZ1EOaWVvnIR+iA3rEldVrkwxMJ3b124fjJCd+wyav7KSn26JzuYTzRqxCh5\nQ9+D62tyWGBsIk0/66/n71pKs6eVHiyp6X1tT2c5S8uJ4jyoYI1Gytyijr4U\n++U2R9sWlz2YHoNVq0SeiDDYhD3A//dhUiEybExAPZ7Ky7sgIjeEWqq1Xdu3\nHSRdFaTmSRA2JkV6BuyssyWoQwhfQmq8bqzcvQDa6wWzeO02UtXJTKU7i7fZ\nH9oq17rU3//BGhAhGn6JryLC1dOFZBoTIA7ENx9pFtiZGwsfBc+EhvIuZHkO\nXwVQ\r\n=2U8F\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICG76Q3WZFKVeP/NnEVSFHTw3bJkC+Y31arFoyALNDzVAiEA3AERNQXzyqeVvBdIhRoYqXsWpFtfim5vWza00bdXaIg="}]},"maintainers":[{"name":"aicest","email":"aicest@users.noreply.github.com"},{"name":"irinakk","email":"irinakk@hotmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"bjmin","email":"bjminhuang@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.90-alpha.0-analytics_1599531686029_0.6797242373397834"},"_hasShrinkwrap":false},"0.12.90-alpha.1-orgschema":{"name":"teambition-sdk","version":"0.12.90-alpha.1-orgschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.90-alpha.1-orgschema","_nodeVersion":"10.22.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-TBFCGilr7NcmMV9F2N4ez9qkWpCgtS3T3DJr/MvsFoGxc6X/usyOJgF8dLNz8+pdxwlv2AiiEyFmPH+g/4yIgQ==","shasum":"e9e64506af0a538ab88895f2d772171360174179","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.90-alpha.1-orgschema.tgz","fileCount":515,"unpackedSize":1068795,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfXzucCRA9TVsSAnZWagAAAzgP/RLNLchEWCyuHueiSIwX\n30FU1rcNJEbrfudUbEc9uonI0XVKbMmbFNFInD7zqKfgIXQ4x2COas4XAsfU\nhyc8Qe4IdC1TIPXYCye11oCn/Zz+MPFZlfz3FRRpEoTJ4O7nfytbutYpZKDw\nnNPsZ3JxUxeQ0tsf0mDc3JZV797HbFTy7OPpEFTm3H8a2+2FpabrTHz8bL3w\nwAoHCahKHxmOC0Sn8UBEGbnKjW7G3B4H5hTrXkqWHic0JT7slhM70NBgJvLL\nkTa+xJY/2CvW8BEFdGEOqTWxR+Kt47QaDXExAqXSV9ANtG4SbBveef/UmbNV\nL342Dl6/QmIaO7nvU1CghKG3ZW2k3s3BStn6NKHVpqOHljKnIwMP1K4bZTpb\nwr8aAtVvgzk8CSyf5THotYsYqTOGyYcs0ZVKv5ybDPBZqdYPjDomLG8rfymz\naVRA7n+l/uH/aEClagj6ZtAc6qOFkdZgnZ9Goi7oMff/2+fzbhFe7uAaDwOC\nuk8NXlJcBRLnJJeHCrE05bFhND80+o92tCE7DVG7nlhhtk9y684EprYa+R0y\nUppgTPcLMiyIlVrX59DTzcIwTFO21Vn7a7rpHNZsGxmyU7PGbnj4fybP2cX+\n1Yh9y9MPaQ7+h0SKYj+BOmYcjvxtMTy1hruC7dOYR4EukhpBEqW/EvPw+Oz3\ntz6q\r\n=ahNf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC2Bw0cl8+4zpRJvi8cuL5gpq770EcFD/4093UAYt/dYwIgRztvFlUoYMyzZTr5S6o3u7kvyYd20Hw1GCvcWloBsQ0="}]},"maintainers":[{"name":"aicest","email":"aicest@users.noreply.github.com"},{"name":"irinakk","email":"irinakk@hotmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"bjmin","email":"bjminhuang@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.90-alpha.1-orgschema_1600076700045_0.6705427809293572"},"_hasShrinkwrap":false},"0.12.90-alpha.2-orgschema":{"name":"teambition-sdk","version":"0.12.90-alpha.2-orgschema","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.90-alpha.2-orgschema","_nodeVersion":"10.22.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-OaZ+i4rWoZBFhPdHBZHAkIttu8SFyNXqn5hWBpt4EmJh4jvt7Jor6VzMgMaMqIMpYu3H5ShJn9SU6E8AfnZIHQ==","shasum":"b384f002bf194059f8bce5c3c63b9230c72e44f5","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.90-alpha.2-orgschema.tgz","fileCount":515,"unpackedSize":1068868,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfY0daCRA9TVsSAnZWagAAXWkQAILZk+urIMa/fXBuhEGB\nWCrhb6rgMabyP3megGmk+ox7MET2lwv2N9plPH0vj48AFYHAaEZDvTyCpC+8\nVp7Kbr3YGG1XPI6hAVv1E5PXcDD4Bj8OiCZm5tl9mB6rfejfwcvmKS3HDeJq\nGutkixd2uC7OTinyab4IZfBCUcXwm9JtIKN0m0h4yyezMb+GhQGvz0kXar4z\nbZHsfoWAhJtADkqg2WeGa/AxV467piTeVgZ9adpvTNT8QEIlpEegTWtmfRrW\nf3pIEXHNW9v+rI3vOIxr3Y9OCFb5nCZgNC3oXAdQtWe36DX6W3Y6yICQTDGs\nAbMiCylr70kyD8QEZVoJslTBOTlZGdio7vjTBrHXWagj/9Tp4INnBQKBhgXH\n6Uk6+d0Lax2VwQ0+BJ4uVaxjYuExWqU3YFrGL+2ZTRbBjPU2lPcYD3Mxpkz7\ncnDyWdXUtw1rNNwAnZy0Owa6VHnhVpqtWAgBBn5EARVcGwKOMc41Jv/L55X7\nJcmaSY4uorSrqegD3hyQhm2t88IepNqet/1gGq5PqX62zJOkryA6dR8nUdh8\nvmzXDKSXMbuYUpufDqcSkb8kNcAc1RHZ8Th8eQdKyblirAyEmr5kzRMyqaDg\nLHDjZjUZOQyfoEmZ90S/PfmXhlgr45o9f/UKtC52LgM66Ud3BaLaLn1zBvf6\n2Y00\r\n=X0tK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG3MWLF3515HMgwg79tVFk5qb2qtrDIqb9opn+YbGaBUAiBD284wcX//VcwBs/YT/EHXyhx79c66jvg4tsDfav+i5w=="}]},"maintainers":[{"name":"aicest","email":"aicest@users.noreply.github.com"},{"name":"irinakk","email":"irinakk@hotmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"bjmin","email":"bjminhuang@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.90-alpha.2-orgschema_1600341849383_0.227411943646328"},"_hasShrinkwrap":false},"0.12.90":{"name":"teambition-sdk","version":"0.12.90","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.90","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-YeUa5pBbQ0koWfLMQxp3E4/nmJVbcPmHsrSMZMAL+tSv1D7uo0rIb47KmPf7DtRWC7qtrjf0X2jUZzYsmsjSSQ==","shasum":"39e860dd1a21a6a5f3c2258cff9d797fdef24248","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.90.tgz","fileCount":518,"unpackedSize":1072990,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfas4YCRA9TVsSAnZWagAAhZ8P/2JWAS81yj6EgaF7Hh2w\nM+XRYcdbXK3YpqmCTO8GJ9d+doLfLGRpSngo/jiu0iFZaF5VdgcrDmN3ST8O\nyXizkeAyahysOgpiCFGAskdz2cPmj5abAqmV3tatvHsy7GaIltKtf3AAJePQ\nifr39WZAz6mVAwW0Vw0zO5ynB6G6qrLfhvSO8yJO1oCb7yVdDQeJO2jDKjdS\nn7p4g00A+f7nSri7KTle/NBFvrQCWAIfJgdGr9iSbpeFqnvjAdrVXpZOcX95\nVGWKa3b6cnRzAmp/AAp5thCMz66PcQzZgtrhRcpY2Sj7jvY2O4Z7G2PPvzAW\nAUb7HKMBCi8jIkq7cqQCoSKlIO7PPQAipJ7ldDhQKa10Sdn4zHB8TR8tTWYa\npvMfLPIXtLh3gARPtSNmuxf1RdFW6FL9CYHxMtMylkBCsJo8V5aY1cYUV14e\nrdXxoOjv3d49Fj6CWxNK/BD1BVvirTR7nnqvqnWSbdw0Ib9qhueNwrVB0bpw\n7tGD1gy53T+thQQIPDJ4HPcTIzlZt9TQjSib2LEWivKf9EMMzpteWXerwWAK\nQ1/d3UFMwpBrljS9DFm3M4OthbCnqkGflIdzRfq03z2Cf8sjToTfFltrGuNA\nVwHWfZn6WY+Bn9CMEs30dJZyyBPgvvz/+R/nb5AbxAav7K4RsmHkET/dMo8q\nj2cE\r\n=cuXe\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDYmri0E0dH4uXcC7zrFJProa5xEi1K7IRdbRRy+v6rVQIgW0oyjkw4xtcZj4+tt5SAOS2LkkqxLoXhUy5PpQ07ElE="}]},"maintainers":[{"name":"aicest","email":"aicest@users.noreply.github.com"},{"name":"irinakk","email":"irinakk@hotmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"bjmin","email":"bjminhuang@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmUser":{"name":"chuan6","email":"chuan6.dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.90_1600835095623_0.2437169054691084"},"_hasShrinkwrap":false},"0.12.91-alpha.0-work":{"name":"teambition-sdk","version":"0.12.91-alpha.0-work","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.0-work","_nodeVersion":"10.18.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-qSjlDv2C1kwQkTzG8iHfrvIGje5SDgBEu6o4vka+K4K/+G05YP25UpRJGXH+Q/PmL+eLWIqkmb1bESCDOrxrPA==","shasum":"9681a0ef72880c4d58679d7fec4fd42fa4ed45ba","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.0-work.tgz","fileCount":518,"unpackedSize":1073113,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfwGYsCRA9TVsSAnZWagAA7jIP/2Jncm52sgTbYQmqiE7r\nGlUOkZ249EyyaEUyFhQSzU3J0QbWPevlN1jU5gn8x5slK6mHk+OrH6aX1sSZ\n5gKUlVFlXrLx/vYI+ZvUI9WuH8TR1aBNzYHoaOFCl5/ecZ68lBv5SLd2cMhv\nriwh6klPJQJLLMKdYI0kWpfqiyDIJYYkA7AMBsbMnNkvPb4FJwOYpgVHKt7j\nlQIwUqw8/sS1DzC7kbvCzCOMyRlzqFICAPgeZd7WEIuKLQb4zom11JId2H1Z\nNHY5DVip0oJ98R3WGaSc1V1gJAePIBni/grVp1nzeDzEYy2kLVA+bbj8iXQm\nAprpfkdPJMLxvg+ls2sz3PS8+t9uZ+egA7JsE3zsTFr0ntAyIS62GTHwsyL8\n4NW7bk+IyKfnxLtx1Yq4rf9cMSS/cn7c3Vm7fo76mQOOOUh2BAIe8Pm0oD6J\n/VRKXruS92VsLuwoflML3FpMHtFwOJE6p7koBsnUR3UhygrbyFX/jXHZy4dh\n77jBlxO1DCvEMZRd6lP544Poq6VBeb3LCfufd/C4gx8ctbGSjS0XmLUDtmfb\ntFJ4F+G+hTvIizmLd7QyTHzdcD0MkCnwkFWlZZcAbly8i1Kn5KcH4mezL0rY\nuK0669qcJmCsQ2saOuoI4EsDUjUlA8i91LtN9VP8B3XrPBuxTe7Ya+VbmSoC\nQ5ZR\r\n=2Xxy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGnLABfV0tO4XWlintWq6AtqfLV8FbxbzXU+iktLCKIbAiAB/XRQ1Aa5VLPQnBb0xBc3e/WucUHlfZGd+tilQkZYEg=="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"irinakk","email":"irinakk@hotmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"bjmin","email":"bjminhuang@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.0-work_1606444588223_0.3253478933446632"},"_hasShrinkwrap":false},"0.12.91-alpha.1-cf":{"name":"teambition-sdk","version":"0.12.91-alpha.1-cf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.1-cf","_nodeVersion":"10.18.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-ibvdkWCyR3RRkSszcDJjugm9kNW4AsRyIzX2LXmBkU6hkSde0AmJQwH5tgm2b39kknOnvonfbKZrV7UQdTAI2Q==","shasum":"b270c94173ad135563f9d09d421ed88138a7ecf1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.1-cf.tgz","fileCount":518,"unpackedSize":1073117,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfxjiXCRA9TVsSAnZWagAALvAP/267iCgB+4z1e3F1Bu+G\n967dELIV///MiCIVM9eCM8B0WEhyUfN+Wgrztb54zhYKaf9EQhljh/Q9pTp7\noizGwbFFsUYD4PMioCSVpMJnAZTx4y33/D+yYADqHQGVrv+a17kQSr1kfohN\nDurpFyfcFrWRsyg6eQEzCmcgYRC2HyKlhSFlxADrkJCT3lydFPwRyXi/CRnv\nR/6b5MMNTgUMnRgdHQ+KymT/tDx4iBWNMtPu85YT8yv552lDOWNYIP8LUugf\n9ZSb2zDy6KUR7bIdwa20/afE+weed5EJhVXWxsYCsC9pUQr1B+RplxPjY6c8\nkPbd8MVrijVsTnOOvbmF9m9bqBrQM3WzkFmCClYaL1qHJo+LQFtv8DffHd23\nDCsEM7eZQ0LXl/uLcCyXBUNrwMQ6dBJbf5CIzK6iRCG3WTvETUMngV/YrM6m\ndAIVNfyNxwwtph1+u41w3lDVwtHJcEmFWKH8XRhZxS/ILAe/QihOiIjDCtYH\nVTuwOSG/TqN1XrJYXAIej4Mp/HI9aWfA5O0N8i8QaA2jFWAxBn0WuADCtdU+\nvbIdTS7cUjGFV9B6KDmvbPT0TBU1qk63sIbVDq7v7Vv25F8J322K+AO4LjRi\ncXhRO4N22sgrUxqn2JiEKw5GdUvTIJ9w7tdlafPI/Rc7nbffaNbNPocuG1YI\ngK/X\r\n=x7Uo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBSC44h1y8q76CfkRfDxbX9eULqYJXULhL2qNviTAGeuAiBJo6cpmr3StEOvN+e2h687KQTM8a01v/UOx/4uxUJyhA=="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"irinakk","email":"irinakk@hotmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"bjmin","email":"bjminhuang@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.1-cf_1606826134765_0.33291930629487965"},"_hasShrinkwrap":false},"0.12.91-alpha.2-cf":{"name":"teambition-sdk","version":"0.12.91-alpha.2-cf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.2-cf","_nodeVersion":"10.18.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-LTO4mZieFuDiq3jnXcplYsEEiXwTBpSfODasJWRf8pmg+FiBaydj+XZAUA4GKDUhbBJguWHbJ7en4JQWs+jjEQ==","shasum":"e6417a05b67fbc0231b90bf2cbe54babf0c2fb88","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.2-cf.tgz","fileCount":518,"unpackedSize":1073124,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfyH7GCRA9TVsSAnZWagAAI/MP/R4OHafh0j2MG8xqfDXL\np7rrvbvBiXTPVu0l0PoRh/jwNTrhCe9JAGDlUjzxJzxv+83ISbgjZT9St7+d\nyt8QhSnlS34Jg+SVu7FU9wrC4EHrTaqTPP6Ted7UpsbaJcC+08SvWRpbABNU\naezVlKD47It7XrKGoF88oidUhZZvaNG6vGAHlT/UXa4fDOKQzi46DiZ1T92k\nGeQviVyHLb18R0IXtV3TqEbTetrK3YXYY2Fp2c0mD7+VplY58qJIGKj3C1sp\nplgLxXkFmWIB9Ern1/H3KFRBPHZTOpVgKL64175ZxPnZX5U8hYKsaoEu70bh\nuRf5frqaKY5+Ue4GrZpz9jeHigeGHTigXImYwW7rrLJTsMU+UPgTFiZlEF+V\npFyZoQkdFZVk+ObpWM909Hzx/1/ozCiYNI5WKek1zft5bkqyWCTq9dRQOJkm\n9wuNydRjaOAybcj0zoJoqM1yePxfUmegtBgd30mIKC6CtW51de11SCXEcAJe\nmQ5G6ApWxwK2NY0zsTxTGphl0JzlrY3zF0mq/j2TuLLxkuLfINbfLDO4hJts\nJE09DUkpH+q7eIq9YEpYk7UBj8SycMxpk1aD4d5GZyDxUyP4qrS22RrNlPgM\nxMyWttOa5sBO+K6h085Vm4IgCYDAvGMfl/iLRX2LpvEM25UEjUrxjD2TTybB\nt4Ch\r\n=Ud1i\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG8ysrLVAidWeZfz/vStSBkfN2KoPdDzsEIjAiKlV6VPAiEAzEbFf+0sQoD5G2tBhLvCWiP1diwysGrUqub8f3ZiMRY="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"irinakk","email":"irinakk@hotmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"bjmin","email":"bjminhuang@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.2-cf_1606975173658_0.4855927899941028"},"_hasShrinkwrap":false},"0.12.91-alpha.3-cf":{"name":"teambition-sdk","version":"0.12.91-alpha.3-cf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.3-cf","_nodeVersion":"10.18.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-WW2VpOvAkgAAKbEZo8LIxC10C9obPYTCm+EwqkFzIfPm2rJI5BeE3qFYpnmLjuF94Zy7ZXtyLlZrj/sNJxSUWg==","shasum":"9c3adf6343b4a6b8038df470df1983461131db4d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.3-cf.tgz","fileCount":518,"unpackedSize":1073020,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf0ZMaCRA9TVsSAnZWagAAxhkP/0AUrjumd52XKRR8EwyK\nH1BfiRDMHQyzfyOgv1Su69Go3Hj7DeA+VD47DAgOKDkH4fDny4dwOd89HVE5\nUz5sh47McA0i/EO3jyOwYhcEX8CUJNch+9/OtmoywlaaGL9d+n5tBEFBjVAs\nC4+r1v4Ojp7A9VYAP4frBlQQow7w6J/2S4KpNgigJaEtX/YdMhbyHEc6FKjM\nm/6GiDq/2k1XL0rLAWKzxKuRWw7J62Ryz3TGC4PWIkMzYDDDwaPSsBU7rFay\n9KzUFtt50onjxeVmaXQUvAqkCrcCq4lyFen/fOihcnMnvNbSRe3BhrtYi60E\nHjb2CXKHFLxWMA6QGjQvMr2YUCc17lfYm4BzIQEJP4zyCf1BphvvGm3EJHiJ\nBG0koNsM7k53zM8dHyyVZbSSwY9P/BFVmjxGHY59JRzYeHTycN6e2E2kGb+N\nShWO7Y09daCduJffVcT10xvSWTb4Tgdc9rszeyHqqmITRA+big/2Odgm1vuj\nXuYBIMQku2oeG2apagZ8VJkMVbKvWI+O5a30L7hqZacg1r2bgTAyy1UjwNf0\nEs2nNRsx8pAeo2Stls5uvhP5Ruco1iYO4ylorLDMD4LeOcNXIS/ZMeluDcys\nLoHZnSl7h+A+LzDPeFxI1cusFZ2F17fN18cX7kk+/iTzlbYaphgRAAVYRh6l\nB6w0\r\n=Bb78\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA+SF5IIOWPfGiCNVCx/yoyqLWt84bGlefFeqi53CckwAiBLVBt9jA4Rx9aR1TnsKoqGR1sLZbUMRJOgv3aazkLiLw=="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"irinakk","email":"irinakk@hotmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"bjmin","email":"bjminhuang@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.3-cf_1607570201444_0.7937345541422374"},"_hasShrinkwrap":false},"0.12.91-alpha.4-cf":{"name":"teambition-sdk","version":"0.12.91-alpha.4-cf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.4-cf","_nodeVersion":"10.18.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-jnpslhuLLjrdLXpIWl+KJzNJgBts3dHpp1vDymvFfaoMitjzwzkJwzaL1FVrlZ/KRCdPypnOy10GdQy6FM2PfA==","shasum":"97cc8de6a62a13edb65bf011c8c3f0a477265798","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.4-cf.tgz","fileCount":518,"unpackedSize":1073022,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf0ZQpCRA9TVsSAnZWagAAigUP/0kxIf3rBP0oNt8viWVV\nmr+XdXv41gsYJa2NL3G4anmhpuFm66JaPguiMvEgjELEPtWMb9Xjv9FOs1jw\n2dXSx1gJeU+boUbz+DKStGWTpw47tabL6yvM0D1Y2eR4+ha6M1F29q9AULuu\nrchq620ddxNFbdL+XhHI1KTfYQ2zjrapXvrjDgnxl8JD4rgEWu07TuhzLnRL\nrWEZ1q3Bq8pN4la8iIm0X5r8q0SKukNPncpGNvcx28p28UpGPJg9kJL6X6xX\nKnn7LDj1OvdMu5kNihH7cqRhLjQd9uo2oV2UPIIat8XQuOGUfBS/VInEr5A5\ntcoKcpvdrdgiGWx3P54T0Dx0K5qxfBtfHwwQKxiSNK3GPE9xty7SMeINbSYA\nAQf96ljzJcVH6R/M156aEmKUQLXTSNt5QcAUEUTudtZda3fICXC8fdfs4DeP\nHo9GFvBz4M6RCm08M2B9aglX7PwCb0Zyeji7FJdUf1rDe4phyPPDqDsNXTGx\n6XrJlUfrF0i+Fyc+QtElA5ZZcr1eHf/l2qrrva7wL71s34B9crGL0nQU2Axa\nAWCDzc66KcXB5PYUCLdavmAiPB+CGU/PXfu59gNttIl7FKyKExkdXd25hqsq\nSW4T0cpJurjq9kNBthqkFaWiZwg5IM9NFJA+EB0NvdRUs6Nvt5dXeaG9lym3\nxpjZ\r\n=24yp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCmMluNw4/V502XBmFn5hPV0IKG0uUkssBNFvp8dvyK0AIgOJKGSCg77WhR/Hl7MNx1JmHWGFQCht3e9g/t4fFdhcQ="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"irinakk","email":"irinakk@hotmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"bjmin","email":"bjminhuang@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.4-cf_1607570472615_0.8532650625598106"},"_hasShrinkwrap":false},"0.12.91-alpha.5-cf":{"name":"teambition-sdk","version":"0.12.91-alpha.5-cf","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.5-cf","_nodeVersion":"10.18.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-7GeZ/D4vj1oRwHy9JoU+W5GjYlmZOOQOiTOISZ6U79aG+0J8rwUqlfH303jyszdrgKCt8064qk/5AKXW8mUsNQ==","shasum":"94a585dc0b6e9ef1549d0eb4bdf8df6f61bfc30d","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.5-cf.tgz","fileCount":518,"unpackedSize":1073132,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf0btLCRA9TVsSAnZWagAA8wEQAJ7NCappWTtW2/tvB9j6\n0ZYVlwZjUbDPdh4WOEtDAbB4c3Bzs/xEhaSu08wQEjwEkiEIvZL4GPVc0FnA\nDE3Io554jYDq2fxTlxASR0oM4ZAJOo6iOX7aGBbOUp0bxbZdO2LzKp+Ws3Ha\nzcl8lZC+IIUxuUXvfU9aLKhwfr99dOBOXxQ9HrPjfocNqCRX1od+sFv9klWd\nKv2+7m0cGUmjIoJ32863Gv9kG/RRPyr+K+Xjx1LouC/aKR7/6QIxEVKBYQd/\nkUtlJxakGUHp0sDsM2EcVpY+nTueSsXMNbGG4aqlrKpylPuXCA/8Hn14qZag\n5Sv/T/o45uGt2CFqqSvHsX1NLuqnY3rZvfneIYyTdL7y1pukOpF2uFRpjkrS\nRFGftqJ6li1UT82nwVSknt37nBTgbBRTgDRl38X4DvorWB+VFcat4pKulfFC\njlYzNZj5N9uAc65Ipl7TCWYSEAb4Hx71sBAXixxm6Gu3tvFCcEs/0toujyJf\n2EJIGUTkSScr1TNpDOJ8hBFxkQNj+xWJjbSyGw9A0mCpijwZsEuevQYZN+MG\nL/B9ZWhoRqBb4E1KkzUlRHqJqpNJNgqAJYecbOcH1vzeanY3o8M+n575ThnT\n9AdOzrF6P0clYEQCzHG7ND+tIjn6wdXNSkzZrZz0q3Jejqu3gdrltTb0XGhS\nlp7z\r\n=Jkeo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGlUX0yPw06jLzXhJLFTNjSc4vNLBvfe/3WdjReH6vgJAiBn9w4IG70181V33CX7bI/E5RsRUJ0gjt0jnJ5NgtzWuA=="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"irinakk","email":"irinakk@hotmail.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"bjmin","email":"bjminhuang@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.5-cf_1607580490719_0.23531939581322336"},"_hasShrinkwrap":false},"0.12.91-alpha.6-smartgroup":{"name":"teambition-sdk","version":"0.12.91-alpha.6-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.6-smartgroup","_nodeVersion":"10.16.0","_npmVersion":"6.14.4","dist":{"integrity":"sha512-mXfJkY1lL53FgMVSJSSYgxN9qk6z7I2LuSfi4htJuvhKOoWigAAv/R5aduNA2u/z2iu91lOmNK8IBq5eZTGLeQ==","shasum":"df154c4c62ff320253d883fd0e4eee26a1dc07c7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.6-smartgroup.tgz","fileCount":518,"unpackedSize":1073208,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf4GKkCRA9TVsSAnZWagAAwVUQAKCA9ZRClTGf0lCYdhcX\nqEeIe5igwj4HIMOY5zw2WUiF5eR304Zi9J8AcMck3u5pnDJD9vEYLZS4wWIs\n/EB1C2M09aYjoeIcZX052y8hAV0CKeigTt9cAyyNX91uF/0PSHaB22qVLv2K\np0TFCZL4FKwxZK+UQZ7KDwgZobvBDnacqUECd2uQHkTf+1VwiHZ3G+b3tf+j\nr4oypFUQMklYj16/plsDeV2dD4TOqhgRfL9709wHBYXXJmTGtQfpbpTmNjRR\nhDOfiD2fgdrsgSCZv4qopRyXd+j9JW/kXRBBSYgh5fIiNQ3nyMK3XhBaDstp\n499+RhgC0abR/qxqHNFi1K1XKXqvL3bEdtdKRDxXhA0Hs1R4aYp5G9EYhzNR\nY1nt+i2iyOkjWp/DRSizpoJOY+xfaWRbbKTJlVOn0QI8kR/LBleieZARIeiL\ngTM5eMCcjm/R/4UxvySbyR2CiF/RHnm0NUP2jqXeJRVAeCLGtZsZaUJUWp3n\n2n9BMz3cszsjnWMzh/78KPLChF7WcTKPx5stvM+Y4+RThPFozfCtWeIfqyHa\nXd7UQQfF8ZIVByVTShcAnUM2hXtbwKr4ZDCvZERVcNDDkJmhuVHf8YhRtn7Y\nlFjUaF7JWoFz0dxpeeR0Ur6LmG4KVbqEPdQmtb+mIH3U9OEo6/m8c+4oN6RO\nFWEg\r\n=Mbdp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD2E6lGTNw96R4c4l5ySb1xDSOTjjF1GAmuK5R57BiteQIgGkyH2CiZjGrsC/omlEwUhGlqTsPIjyfP7voLYcs/gP4="}]},"_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.6-smartgroup_1608540835875_0.3366042207692401"},"_hasShrinkwrap":false},"0.12.91-alpha.7-smartgroup":{"name":"teambition-sdk","version":"0.12.91-alpha.7-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.7-smartgroup","_nodeVersion":"10.16.0","_npmVersion":"6.14.4","dist":{"integrity":"sha512-1c3Z/+xm2dnI0GLs/MjkKHzGFfz2GXMi3l7Aymc4nDmLs2dJAHq+6CT0IcKehFrTP22VtupzzCFp+yj3BcHjUg==","shasum":"a4e90c2d09bac07b427e37cfd980668817c21519","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.7-smartgroup.tgz","fileCount":518,"unpackedSize":1073416,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf5JBvCRA9TVsSAnZWagAAcWAQAKIiFVVxQmAFVQwNTShZ\ngXEsZHFaHoiMSrrhRbyMaM/iaOp1a2MgVLo/QS5VpX3vsLhHCGvu9KK587r+\n5m/o6P7KWOeCtu/tSWgU2pIiR55NXiA2phk1Vrf8A9wtqQzLMiop03Io5n8A\nKUAZqjf306GlfzbAvjez5wPandTtgJiVB6kq5ZmKkJSt146uWPPWQAo5f51d\nCmKvRU0d54mAc1Rzq61+mgZnf/5U3cx7ebpfUdGUWE2SE+BU+LNJxLn1j5Ty\nrzGnex377Mm8Hv8n3myRBePMuGd1HgESOTirQWq9I41nwUsKRTaGr/MmLnYX\nSR9hwuou70h6NL4Rr2clRsDPqyuBThOiLrxsGKyOsWWUs1E2PpRJgBSnIXWF\nBaT0bpf2TRzkAVUGy4CAS1Sj/75ZQsLP1rgFe3LD5nLkJk7D5j/tyUSCO+b4\nhWaEsWmhIDvOoEMK9pzLln/YdyTxMSQGx+XT7w2UwjnoYI1SyT3Bv0kmFUH0\nfOy6PALrmTG5kbg23RvDXgPqdv6CPM8aLtz+Q6REAF08hgbdMWIJyWtn5GGi\nerd1eEsXXUgOBYi6K2Y/lqrCK0G5fzhl0lMt171A8gNSujuCez7GK3mD5xgF\nsQTjQXaV6O3r2IiF3r0DOec1veo50iJ30DqXtW8OD5kQ5mEQC+Afumnw7hV4\nKXwe\r\n=iX16\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCoPKdFIvUZafsvm8czk/J3sJ55oqPeoNX6Fl/SJ3ac/QIgRj5iQ+SJO3mC5CNeqX3wM4YvRFskZiHKFWOuJoF+pWk="}]},"_npmUser":{"name":"saviio","email":"sirius0x9@gmail.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.7-smartgroup_1608814702598_0.2777440037245913"},"_hasShrinkwrap":false},"0.12.91-alpha.8-smartgroup":{"name":"teambition-sdk","version":"0.12.91-alpha.8-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.8-smartgroup","_nodeVersion":"10.18.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-F33gYH0jSby4ZEYf87E9SWpZXNkZ1IqpH0mLpRoAv9N9e89dom7RsWpJYeo2Zr6fxV6Vy3vgvDMUrfU9fTih5g==","shasum":"845dd9f42f9588a0ea2f9c7df810fbb648a41cea","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.8-smartgroup.tgz","fileCount":518,"unpackedSize":1073547,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf6xw/CRA9TVsSAnZWagAAod0P/0ln5kS3Msx52kT4b/2W\nQXZ1ZOS+3Q0CZ6X+Bg0pfOvZHOygsErsEoLohHtNE/ioBo5s4uezEABFJQcs\nbIyVwrJh78sj0N1zL7hw2OW8oa1R6eUU0v/Edwvyd0lCd0QQ1uCiA3X95BLT\nCtUhbhltuL3xmxDnBC7ta3JfDC6+1RoSmB06Ix4Mi2WoztqUojmQ4TmB2maR\nNMbJX1whN4dAw6lKb87pCHlPKquHKCf8MCH6PvkuaKs977YCfkyPGNb3FK/q\n3ztvvncFC4UXbOJfd5ynCp1Y+nsmlyYiJLNse3TiTcdfIYtYwbl/e7U5nTmM\noSUB3QKwOshRKLwKc6pERmsOyOHrUcEaXzOBHBQqJeH+FPKUl3inrufYtXtf\n2CFS2Lef5BFOxSz2U9D0s2r1zhJRsdA75tjgOylB7kPysaqt2KN2fJDu7qv1\nx/3+3vcahIv1ncMyFukVLzzWlOEuQAceTnCzE7quIZbSJMtXssQkvuErGtLp\n3VWGGgL9BYHd24YU+1+w8q8xnbsr7sXr7+Exa8emNZ+2ReH+V9ASVi2rnTl1\nxgH28K5wPBwsxLZDFM/nfHulJ9PwwNHDn5dTL7W7GOfbEzWKqZcxFzgcBs/2\nn7TrApjXCJu5jNgtVjsw3OmuE3Q+oZrH/IBvlPd7eunmltD3KeFsoXnbv94F\nXI+o\r\n=Xe0U\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCMfQw5J4h7yQnaQw0UNAXkFkNkNLo626Rh10MLcGAYagIgBqX2w3BrBjYypi92LsoGqCFwEAGqvhCKRfwYJVN+SIQ="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.8-smartgroup_1609243711292_0.0538624308582214"},"_hasShrinkwrap":false},"0.12.91-alpha.6":{"name":"teambition-sdk","version":"0.12.91-alpha.6","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.6","_nodeVersion":"10.18.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-SwfR02xerqoQdACw30bXNU7v/6m0ZLXamI7QGPjHEBVTS/pF3TykICat7k6vGC39G3xcG/py+WWITa4oc9jeIw==","shasum":"b7eec287b0ab0d94e5c9ae41f48208d01f262344","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.6.tgz","fileCount":518,"unpackedSize":1073332,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf89PRCRA9TVsSAnZWagAA4icP/1O99n907FXK/EoUGiC9\nP2w9c5T8Nx4YzVsU/LOEiYqqjtHblsp+FVdKDpPPmtXYpgyQMVPnLDkXJInf\nQwNUNj7EHo5bEY2BrGpv7Zcg6tqd7PGvcNBTdnDg31UrkQoNz3Lk515C+elL\nTlaLrE7hRo3lQoYHnbc60tB3HEbYe/ZP46IZjODgFB3np6rHz7MXBSIvJG2E\nlRYng6bX2LgBHpz3ql6t4XWPkHzAXh9a8CoXnWly4BQx211m1QwOq7b86hZ9\nMJlqfiGyiXwAtzagAVSDnOd0ht2Jqh3XeGPeY5xvkQ0x0TxnmFg2/ESsN8SY\npNIXbX3zOTv/y9k7VBXuyamjPP9pnTcOi/fdTw0qkpBtXNoYkMPT65errH9X\nHqTpI7L1FwcW2FGDbtizyUlOIxxQZhM1S3iV+6wJmGenSiUHixiRpXEcVHDI\nC9n96m9wLn+pkC2i0Eo9P2YX50PFixyaQfpQ01++jPSYOsW5+0UkbkgxMzEV\nUHxu77hufucaV1LBjUlrLPsebYz/uNdJlo6MvJVwu4GYdV5EPMxOoypekCPm\nzv5dDKJtCio9seFuZUMI+agDaSZOXsdcGKgjeRS/tJ9izHvi10BYISulv1Wi\nTKfbDpE5YMd9CjV7rMmpPBw7mV4m4IL7tU1Qx32sMXYqpk2I+PSLqV1ZVF6Q\nj3yV\r\n=sx+P\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCGxKECO3SWSB32AVxzCfcQWIFhSUnBc4qG5AByOOqHJQIhAPMH9g8inRdLyyO2cX4mOuMd4bHoMfndu4pBh7TysOEx"}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.6_1609814992400_0.8184766745254095"},"_hasShrinkwrap":false},"0.12.91-alpha.8-pos":{"name":"teambition-sdk","version":"0.12.91-alpha.8-pos","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.8-pos","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-zkBBlHx+ODnKDrTV5JBOzvkiZ5k2tr8Q6cMy1UhuqNJiONcYIA/GTpi5PiWByzW8LffTyKN2zGPGVkKL3cSdPA==","shasum":"2aae1a2d5771aa8890c8c0313e8d20d4c08363f0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.8-pos.tgz","fileCount":518,"unpackedSize":1073237,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgBSxUCRA9TVsSAnZWagAAjsQP/3JXL2Cd2JTnX6rKaSOF\nMy1QTmlyVdAEJB/fn7d1nhL0vchIg3pmlt6KmdnEUSbUfhGj81kYkCDAEbPc\naFwEM6RO13/y+A/OfU+iPGGorwO6hJHuibAjfru0Ic1WlpVsuDFhcbeqWZZW\n3aMca5rTd2wW3VMK8DenmxQgyH/BBB8lBedbkIFtDeIqJP1IJ5RF3gr9MNpk\n8OjcuhI7R7qVn9Sypo0AB6A6/Z+Ivw7S6rnx1mNTMb8dDi2Bh8qed8mOu2ew\nrz7CiPxZDG/0bPTx6p2yhGbZ08Ebrj71cmcevIN3VaQuEa3v+a+dRwuQVGAK\nctWllb3Jvh/iwxPVxhae8C5EXMuoHJrCEoIT5vl3WH/dCvYMEInH3vVcRa70\nVoRkiDv1ShETQPA9t+XqlY7GgS07+zutucfBJ6My7vPotd/PZfjaqJZR7ZJv\ndyL5Hl+bmAH5d055XGZMvXRLykkJSgDqWKnamNgXdtYRKs4D+vUb5vSnF1AJ\npCOwctGgsRvw/wrGG0OysRZolbi67V+EGPZpbPSQI9HKZOZ/iMlfIovMikk9\nv0Ge7xhiO2zK7tzRfrxQDdlcCEz7oR+pcxpYehAWsdeERM7vWES54GE/5z0o\nJyxqQzdfPxWbOE7Nx0cyjyl8tgAMAqgJNTAM1guaWnXhFEeUaAECgOa4Wj/9\nIEuq\r\n=94Yj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCeaR3mfKAj92ay4RC9ABtqnhC6BQXoaehm4/2rXOaPlQIgBS3g7dWDByuN6VykujUogxI3J6/tCf0KIwgTK5CISYI="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.8-pos_1610951763643_0.4072351429910013"},"_hasShrinkwrap":false},"0.12.91-alpha.9-pos":{"name":"teambition-sdk","version":"0.12.91-alpha.9-pos","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.9-pos","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-z2Ya/o5vfbSiSKZwEpNch4+1sPtNnQpvo6Coet8GOtulYD/RZGMXWY+BzhEx5X6dUPX43Er6geSmd5qIvAiP/w==","shasum":"e21a221d619c3555826079630b4cc817008dd2a3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.9-pos.tgz","fileCount":518,"unpackedSize":1073644,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgBS8CCRA9TVsSAnZWagAAEtcP/1cri93clAVqFFXueXrt\nvUTcnDhF1uNNvQ4FUjaLu+0YdU8gZ0JesNyf+QZO9GsZlPvZCh47pf/CMJGx\nuyN7XAh4dX3Tjkj22eV2HCEYtUzFm34JSxvpaDZZCXI6qhahABecBAfDWCvl\n1FPYWzddxVXwATsPt9kRPn7ftjddRXLton7ASKu77wRBJdsu3xnOfTThD1yY\nTUtWz9Pd+oH2/WoIhBaNVxJyH7MDnu3nw3mdsnMbAnzS5r8I1oatUF5YL7+I\n/FkmTyi/TD50eZnrxKz/NB3jtgLTfbEoo+Tj8DE6FOGmjuk2pIfn9g/wLkwp\nPhjvlr7KbqnI8i3vt3OYdnVvf6u/fXfULgBhM24EvLAisdItWPaBnRONISKx\njK7aZgAgtaUliUuZNsQ0dMHF3qOVKa2YCjz+9TXcuKl3f/XlUJEepoqkrFjQ\nzrRZC/9MQAvUzSIR3OI0Ff5Cjw9b8hzgMmTDo1WBbYFbqxhV2wQUb1Xlgv0H\nZBUkjt3u9L0ii6d7NGEwTx1bJ2xc5TRl+ydmcl3n57tkzyynSPcd1b+0SDYE\nGEpoBUi4k0P13UVceTUnNmQaQ0Rgup14QIItDdG7ru0YmW0LYfxgv/Op/aQf\nssr/L4LfewGXsUYSGIM2EXI8N86MW8UEWOWgU90OdPZrZzuZzIcQ+MA7aFdu\nKJkH\r\n=Bwmj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDhV4dCCWyc6AE8/hwtpYzQJg9M5pRX8JjHN5ToVwrzSQIhAIIrDWmk0QRVTzdgy0SNV/6X19X1VrADyky5dF27CEKi"}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.9-pos_1610952449687_0.9582635831497963"},"_hasShrinkwrap":false},"0.12.91-alpha.10-prole":{"name":"teambition-sdk","version":"0.12.91-alpha.10-prole","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.10-prole","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-PM3cEMIOwIyGOnc3h7QHM7LR4CcwlXE87LB5ovzA3leKSgzGehetx9byuNGudEzPMd68SuZOiviML2daPWb50g==","shasum":"a27b9647c6bf44b8063c771e2161911749064fd7","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.10-prole.tgz","fileCount":518,"unpackedSize":1073838,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgG1fCCRA9TVsSAnZWagAARpoP/2RP6dLM/Eg+g3suEi+R\nM8JCpY/s21tCMQulKED5UmKqkSrZXw2ydoy8FGwIP5dpAt1e/QVbxNFgoFX9\na3rDg28CZDnkaJnTwwWHp4ccyfr8KbBQ/0eyxRYi+BOa0+cFbx/nSiFt0PgY\nOpjWowPw6b2o4J18gPjz80uQpSRQYNjU8DAD/j/GqLBOTdvhjx6qs0HQSbnn\nRiu+OngZJsnyrxE0NFYsVt+wt2lnmVII8dgqi6d+/cTzNltnIS3Gs3luhoi6\nrV1e8nGynADIm6Qm5qt2xUSGsMF/hpZ2o0J5a70cz1lVQTdSU8Gs/gxv308V\nLTehVQEFvG6xpq3fIQ1quufbg0U1bwNOIy0rNE7PbEkUsEsu7qVSKWC0tjPI\nHZ9XzBm0HxP7F7wajYiv+joD6SrJSTb4q7GayXwfW+MU8AE52abeeiDR7hme\n3YcWqHhtuZggc7duyiKEC9kNhvtZarc+h/Zs6NgHDPpAiV8d5EZLWLh2jLtx\ngRZbhXj6MAyjhWOHP4MhlgTIBsBFHF4u7UsniS5OsZXz2MsI34xOuA0eGFBF\nq3YJ25Zvagqel3yPDQBNHDPGxmwCXWGgvZY5zQJ2yySsNhRBBAY76IwPD4K0\nKOWu8nPB+TUX46YbIZCsIfj2dyeUPbo3kgCH3Xot5TIQ4zePwTDZ0g6uazzl\n9Kfp\r\n=Rhgf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDwWGTP+r6jsZ2ZLCZsGE4mixrp9pq2KvBlcy6HJXDLEgIhAMVFwVV8scvJsEiYniJuCNJyH0FCqpJMdA8mony+lao3"}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.10-prole_1612404674276_0.9667101611608184"},"_hasShrinkwrap":false},"0.12.91-alpha.11-preference":{"name":"teambition-sdk","version":"0.12.91-alpha.11-preference","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.11-preference","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-AgZLjWbq5QeUBvSjQwrU00KXNi5oKGth3wD2HVe6vmTme0qzgNz642c2upIjbOYsKDMWPprD89x/wsIpZ6oJ5Q==","shasum":"900d06e8415b6cb654f33bc577dc96f7084d2bd8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.11-preference.tgz","fileCount":518,"unpackedSize":1073779,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgH2UwCRA9TVsSAnZWagAAKvIP/0FXwAW4kloifqGfSeUz\nkaQuCnLgdaLbC+8QVx9/Z5fomBl4txRotxOItkCxHz4iTeHtWHA/cF5zj2ul\nnZuC0d2nKF5J/z03DCN0Disoaa8z6elOSSMVPYs/OtP1arVBvq/v7TA/Yhhr\nIQNSmoLk3NGmK9Yf/op3d4R8+QZKFVlpF6wey/+6bY+v/eJWZfxeg0O7pYt7\nxbF0KDq6knJhP2jTdcUQheWNWba/CCV8ficSHHpLyQj+R0VK0yhlENPNid32\nbtX1OIQ65q7YYcKgA2/FT9XJYcsJRfFq94zIk92a1uwQMmGXwo2GVFKbuSIm\nkgFyZgsMfXuioPdXTb5njia2Qjuc4IgNr2s7s/grDJH+DSYXFJPGCzWwsatU\nXzqsHWf14bQT00y78ajUEH0FPDkMZHw5ydugMHUovL9MLFkB0jl6l5oE4Wmg\nOhxw/hdf8vWnTxAW4StjAwrQSXBSS0mSzNShBahHrIMzUHwHZlCu8YHocfhf\nHUv9kqwPWQB3t1Sq7g9MGmH/eVrnVEch/0KzFUl0q0ER5gIntVbkCQnvTnP9\nZ43UaFfz/iz/3rlOKE+EQCioBwKDJ7r6dA0+JSLVJDDPzAr1LMPRJFm9ZQ8k\n16nmQNA7Tl2/g725j+eFurwze9ibRDLD0SYz4oydNjQn+0cKY1axjJxj+bOq\np5T6\r\n=A4uF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDlyzZoi28sQGwFktYnoOVeX0e0G+XNHvw4NG8SNqKt2AiEAwH57tk9TPHQ9wHv5Adt8sWobu8w/2OG6vY/qo68/VKQ="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.11-preference_1612670256140_0.029323979051980364"},"_hasShrinkwrap":false},"0.12.91-alpha.13-prole":{"name":"teambition-sdk","version":"0.12.91-alpha.13-prole","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.13-prole","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-lzmifOLUDdTyAvyImM8ASo7OBgTDNVyINQIx28B02lnhHrBgitrO8bGkzF5rCRFuOM3o9YlxSFhwVhZMEsY5FA==","shasum":"e101ce482ad46d918f88679111138baa2333cc6c","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.13-prole.tgz","fileCount":518,"unpackedSize":1074204,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgI4P8CRA9TVsSAnZWagAAinUP/1VsNm2onmGWdlOME+ji\nACP9IVrw94ypnPg3LHHxJkI64UoSFDmQW+VNLo/gBMNUiQDWcbEaoP0oxFca\nS81RCWQBbShjX/kx7d76uaTCcczipBlbgWL6UK4fkveJte/0CtGsA3OTUWGZ\nVrnCPIedI6orpwM8ZFzYoyDOhbokLSYjOiB28xkhTVKQwxuxJN/6nY05a+Rt\nXWTIpLz4cHlzXJT5Cp8SS2WuwTr8+bMOvsRQI7dsUotUJiWCaVf/AbTFZjYf\nDEWSyzk662TFoEiVxubBTypn1I06cVweyhHrvuR/ilWkitwpyLhujpdX96eU\nGf3VhlwP8A+fV3Z4gyglBE/sUIQ2aqwP82FBvhhRmbL7TBVyTTqpHmbUXhpE\nMgw8tifIYj4rpLJKug8TjvYEC/HB/01GaTE/PLqF8DqP667gzhAihU0hNC7w\nGgqJZUa82CqqRJpaYfjDXIfgpIac3MuPjd2IJN7NvYCHuvPr86inAaQ5jnYd\nXjjOIxd4Db+8pzNYHUr6uEgIxkXiSr7WMvVCgvkoxWeTNCXdEAmF05r0/+eR\nEN86S4jFCL1kxpSUuLiY/YSF4WljJKZaWXGS5Us+A7FUv5Ysx5tklqt8s4W1\nKUbyGpsu/FdmPVWdLDrJv+hyus+Msx6vk9gsRDsz95lq1IWtVjPE1yyyTIDK\nJyV4\r\n=aBJ6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID6hSPL3JaEQd+Jv0BO8KHa347MIY3JQe8otMoKXjq4KAiEAszQOVld6ILHxYlya1oJRDl8qca2SrwrHWEAecpCOSgk="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.13-prole_1612940284065_0.9928229779504645"},"_hasShrinkwrap":false},"0.12.91-alpha.15":{"name":"teambition-sdk","version":"0.12.91-alpha.15","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.15","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-tIL1qaNx8H62G1SgSYmopLBaxHNxWagpPAohZ1jYsbIdCDByUoCSBOFbXQGiQpjtMXuZM9/7btC/DTzFhx392A==","shasum":"33163e2ab5d02be10ccc961291704171afb8eb6e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.15.tgz","fileCount":518,"unpackedSize":1074429,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgPeBfCRA9TVsSAnZWagAAK38P/18pDScAVtD4SpbXdJ7/\neH4EPgYZoEsCcCfHTBrzdiFic7yUJKjBpdfIx0iiacAW0HM9v5lz74N4S7wY\nnO1DKFH37voMEpcFlzoOcHTNq6dEta/xtcSOPsidWgf02y1i0GW6mnJ6GQwO\no6eIGoNxZSHRsm7vzbuAkSWOVv7XbFhDQ8oZPsIAyHScxqAhL88p2rTsKk59\nQf9F+Tg8tx2/WKvUaebD24Zdmt9Gskov6OARBU2Y1GdDohUkZuZVEw6R9YkU\n8miVakuPopx/3pLyReQKFKMoHPfYt8zHeR6rFakRhlQ7iTKqPuMO91QDWj0h\njB5Juo9XFX8fzlq+gOa0nhgMMk4kyzqCZKqz4DCR+GYorwnjw0S9kh1AOXyH\n1tJcwxKjEVK/HmfINjFbRxChlP6AVkLyMYfnMEg9Qh/A24cm7hRVrCxXhv+j\nl2X1rFyDrkXj9Kh00O33j/DvoMebfNUB2rR74tqgggD36d/9j8R+9ZH8QJP0\ngqY1j29Hr++az7dwuXjsZSRNWVCWXtlXtlkt0QRdvBuvvbL6hjG07YjxmmQm\n6zBXFdhmxYyD9VAXyKmTJ6n45gSa7Bt9WeXeL7E8lmZWwNEDgYwmHyqqJgn7\nUE7OUk9U1v6BKruBp17KJFfrTd34T2FWyS0JKDzsNZ1IaXSLKRxZffHa8T62\nJNRT\r\n=q8v1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCvxuRUCgHNtswcgM/d8EbSihOG6hL7h/SKmTWDotHErgIhAKfESgv4zNOuObFl5dfewetsEYNNqGFZKrN56XqMJ/2t"}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.15_1614667871264_0.8888616444476314"},"_hasShrinkwrap":false},"0.12.91-alpha.16":{"name":"teambition-sdk","version":"0.12.91-alpha.16","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.16","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-rLDCyLpmzCHRjcTC4vTRYndrLbHoN9DLeT+cwxqSo9ypsVAO9dDfIMGDSIq3lOjJqk1p4rr50AtCRRxISo93wA==","shasum":"fbdf58ac9348b1c38d5161dc7fdf47b53d8ebbf3","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.16.tgz","fileCount":518,"unpackedSize":1074586,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgQaX6CRA9TVsSAnZWagAA2REP/3pbadckyU+A5q+nhL6d\nB0o6ARKsB9iH5EvszKL8X6PH6h+q+smQlEqER+tU0sw1gwQyeh6YUoo0qG44\nobTt4cqxads0oXrRQh0Wi34WzARtSe1/TfwUKesfOhZqCz9ooaAm8M8g6v+E\nIM+jV0xrNvdNKSX1u2Rg4qLeYCbE4sPUlUMiA2WKfFMXsUgvW5Ex4ng5l6YP\nkvZUloMpRW+Fo4tPlfYwneOjr2ddVGcKTVmgXdRRYn4ghRMLAZftgZnlHZ0K\nV5Q2zlJ1Wy33NKpJ17f41JKDGLhtuGqxXvFbaa/w1rv+ghi+yzmnJbDUVXHz\nwCKeO3uIUjNRfrNunTqDw5MppysFY6fZwwNeAqZzPhOe9dDbKBQyfTejbed9\nOg9/q4ytUX6XpgwLa56uaYl4n/9CVobDBevWVHQZiDp+CRaPhqrcbgOiIG7q\nd5tH5n5a7DU7NtkKn1fo3D+erBVk4dYRizCh+WK2UX4q6/hnYd/+SMptcfE2\nHyh2HcyrnFTZdEnjWrUAg3VhTzuFaRDDryGp4GCX/CqriQ/OGkG9dsqc+Gmh\nLFmxn+pSwCZN21kUHPz7aoYikNRguypXaCEl86Ju9v7U1ZSiErlsQPsolBiI\nUtGznZYI/N6ywqDhdrTahi3WjigJvyKuB7ZoN7mtukBShuGMaJ7A3G3OTLYp\n0jtb\r\n=+AZ9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCw5pgRyCGpHBqfWLw4WffZs0wWWiwJ1UGSo1C142wSOAIgPex6BASPsmmZ3e7BXckr9fnkbYMzLT3mDVlfAEUBUGk="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.16_1614915065681_0.1777971366204143"},"_hasShrinkwrap":false},"0.12.91-alpha.17":{"name":"teambition-sdk","version":"0.12.91-alpha.17","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.17","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-GgrwkwV+0IC9FjD7WFheU43pz0RhL3cAJZL18mhf2GKtnf4EecLZIHOsplunnb2QLBxXHlKRkisyv8/2GcW5Ew==","shasum":"01e093515ad49d1f0a0673ace7df6c62c35ddd49","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.17.tgz","fileCount":518,"unpackedSize":1075264,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgSz5xCRA9TVsSAnZWagAAmSkP/1WeCgRjdTPdUQjL/lVj\nxBpYUPSYm+NLg4E0wKjQWtOiT5BUy7rrKOyoquGgn+sEAJlJuOH/lI0SVVNU\nMjUtgjhvBlIJC+nUpGGe8CZORLL173vJcbfFXdg+fak/V909j5hIpRzN/w6Y\n59iVxeLF/8ytustovgh7xi5QqcPF9Z7YF6kt6Tdv+nNotPKLN+FwTIBbaX6T\nH0OkYXr89ONtTtEMvyAjumUkqn0ZXjeM2OuC7AqibfOHZ7eFczFfYL2sZMM5\nheRmXymsnfVjFcvvNL/hkia3SwByqwVLu+XxRzaPtEiyG2Gwg171mS12TOAl\nGF49c3RevPrORuHjTlrexqQroQvkLM/Z4WSDNaXdMxRAbGdZMR2Qkuevt/Ef\ngzmvTT77wWIt/zq6ZQYA8Fc8lAgRSxptDlJCe16WpT9vppUyYLsInwKd8ZrQ\ncPMU6rw4JZm5F2JnxdSk1PUKy+WblS2roBPi+F4bEcJDA90ya/H+6Whc1a99\noTqk7AyuBHyZXy5IGxXhfRwL5PfN3wNjMwTQnyNtjJTyHPU3zuTK91ofMsmL\nrQJ4HdTrWsqcQPc9OX4ey+WpCZgABst/zVNS/zJh3rW7PfaNfSSd7jfha7HU\neYkrNtENuU/1/GJpBjY3LV/LvzHVepQh1vMIcO8TXnNYg2p0bCuvIHfmW2I6\nwSoh\r\n=+Ayj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDX2Fl+yxGnaUbNnQ4iNkyIhaOXIqc//G5HelnGWA/RwAIhAKfd8nfrcEj5pG1ywCqqneMrxnZU+saqArtTueJaDlaA"}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.17_1615543920444_0.9842942869988478"},"_hasShrinkwrap":false},"0.12.91":{"name":"teambition-sdk","version":"0.12.91","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.91","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-ZK6XbwdSvV8l+HlR5R5cfijr1ayICKN7cbv/m3jpIszMj3pM2PBGNGQVAgo7oGTA7onTj5wsUVM+ilKen5dtXA==","shasum":"85179eb7e5f4fbd8d6e2a852c44568dc1f571095","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91.tgz","fileCount":518,"unpackedSize":1075240,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgWwL2CRA9TVsSAnZWagAA2IEP/02eXT6oaTd+p0sle4Kr\n8E4HIlohLOoCFrJZQpRBccKcd5DLZie8AJY3EOlG3eX3kPJfs826jw7jUbLo\nwrjSCGMUeldU9qs7rTAXt8r681SL+N+Y8lKGB27lrTwSFV6o2zoIxPZX8nuV\nxFEdHBNGMD9C9bJviNkX7cnZpQkYSAasqjRc2CVpxY+Nh+XzSXY5mxdv/aaY\n1CvZ91fwpnwUNckdfsgOGxS38sEf5xbh5UBRblJDjyPVvFPnpmQsH8quOlMd\nS2sm+2rYiLR73u8OhGJEDalJYoUoFgYVz8PpQ71hkP231up+I6DVL0C3LgxL\nIxX0uL2dhfvwUyFFl4OpQIoXSY0sTUNZYXVrNOKtBJXRvplZx0V4/3IPrW35\nTQn3vMw8SFs/6piypYhrReUfZGwYIGuxLz/7Sl+94F85ZpbIOTjF94ykdSuP\nmKrzLSjXB0MCSrNW4J65S5He7PNaKsAA6/oLFy39y+jFP2pKO1zt5//DnqfK\nT52n1FSHphZxDuPtpCU1aoeqK/iRF/1rnDAcoGGvnbnb8GwJfQGtzsU4YV03\nu4Rdh6D9VxXE/OO5dSrWFa8nQgBQU7OfWUAzudZ26TWzw7qGMo1mSEH5EE3r\n2YWMpbAau7IUiXnpCwJ3DMpFAIqFRc+Z3XQ9IpeRV8KtecsRARwAUCkw9Xsq\nn/0j\r\n=MrBT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC6tF90ECC38F+f5S/hTHeTECm01AisEKouGQOl99YHwQIgDKU3Qy+Oz3eJp6iz/G259KwCMxKxx60DjfDxQASzUpg="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91_1616577269973_0.2042940990330806"},"_hasShrinkwrap":false},"0.12.92-alpha.0":{"name":"teambition-sdk","version":"0.12.92-alpha.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.92-alpha.0","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-HuTwoIqy2DP1KlAhtnBMtLdJOgJ7zmG2NEoq01MpN1fGA6X0M8M0ND33a6duuhksoXvraXvrFQCHYJGWVlTb0w==","shasum":"aa6a330fa40c453e929881c22b753ee97f290684","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.92-alpha.0.tgz","fileCount":518,"unpackedSize":1076592,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgWxtHCRA9TVsSAnZWagAAbxsP/1fJ3Qs2trGtX5kUTA9/\nCn7CyZXNrD290ubhe2TtmhVNzgULwt0f5WOB8Wl2qM69hZPJh81lIu1proVs\nJ5bry7PXoHO/00TIQSaKiWumbgEinmLb2/9nSL1aO3zC1gRrIm23gq/VQ0C6\nUyKBwsXmGKGtcvt3JQg8fhTPnKexlJm2hPMU10t9zrOp9qZ8A0CxAjdKZUOh\ny7wVCBLwlfWpPsvKDLTBmBwn/MFlg2n8z9SQKQhH1db7a/90aWDcX+TA2e7w\nG2eYaWH6HmTailcSeLG4k3BnN+YPe8rGk5GZtQ7ayaI3uqoYpu7phxBbfHq/\nkEHLFRJ/oLX0gfs3bwcN5InfLgzNtzbv3tiPqO3mZqHIMNUmFT7KA6bI0MBk\noY+1O7BWbpjwuZ5x4T+zLkjx2goLhleKs4IYo0+SIJbYOkPk5Oj8m9B3ZcVE\nG/9DRRDo+PJVU1MUlKy9+A8zOnvKKuMIiacvUhCRkWSjNNAqGh/IbJlSMwFr\n8t34X3EXk4Z6tu120C2HRQ1vuOOKZLle1Ij6fjgvgJRYPz/D22Nqli+UcyUV\n9MKujFdFVRu2q0mvVD4f2CWF3JigZsylRocDEKeGxzGi90K/70VxQeL2BDOx\ntpFwRho1vzD7UCLAKLzWpjDvhKyCH3TLftdGS2rD/yLvFHSKsc9dYCvY290F\nkB8q\r\n=sq0H\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFCzxfI+aZkt3AfYYF18fUI1t9SNX6j3MSK6+sbxtSoAAiBtwXQ9t5VSWyQZ7ZuIteNHQaZmgYPmwL5kJYhDFwsJ7A=="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.92-alpha.0_1616583494640_0.5819184073049197"},"_hasShrinkwrap":false},"0.12.92-alpha.1":{"name":"teambition-sdk","version":"0.12.92-alpha.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.92-alpha.1","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-xViaxzVDJHkgwIj7COvw+t8ZEJJEOO08NoaEMODzK+NkKx0mAZ3fqSsxPxLQcs69jOUTMoeZqBxH4wmD7PON2A==","shasum":"10b7ffe3d9f2320f3f19ec6a6be5b6811166c6ef","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.92-alpha.1.tgz","fileCount":518,"unpackedSize":1075914,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgWx73CRA9TVsSAnZWagAAFvkQAJ87L+93qtS4XT2Sp481\nsKChREoRvkYJLDiR6lMjLdNPVY3gPca6X8wHyV9HkPNdqS1+IDzKiEO+YSA+\nVVvOvSQwNCsahJBUcGVQkiTySwSVdQv/QySvsGgcGdaj7/AW+S5KZSkWcgdn\nMsvRXM/+I3chRgcaGPMnNP8D4kz8rYVkkYVNCTI0aOnPzQxAX0S345DMj4Mk\nR3aBndUdbeMEHKjROp6xCbHnxcHOS+KEnGeYBOxQZTdv/HpDRJfKrgwGcBID\nnb+ZAuoa9FcpytYIwQY/q0XFdEwo+Nepp8fj/QfHmu1XTAEKZawaFllnDIni\nRKEk9cxVeBtD89+bMI3xr6D6L+o7D3kEsxS6cSnZn6TfaIC6C2Sw/gFcEX1f\n6VvsdjvGuWwxxA64Jmlj0qCYpcpvWDHkjvgD4uefQs3m0Zz/SpXuhgZQDLg8\na0jlP9UVAnZIxMc94qaKIjdEs6AQOqjwy25odP/AK2ys98lJF3CwJqeWA3/C\ng5OMXcWZfc3DMjhJT0XnUj2a27o6sKZBaYs6vjSFCzoWz3cIu0SJVCh347LN\nefemPOgIsCsgIT5VmubvAtJQdfHfKqEX0hgGiEpe5yb8QHoBjX47pcppGc25\nffm5TriQpTowHiraDMsyP8nSXC+PRQt8IsG9dcUKkmJc5jLmFNdr7AC8Ts9k\nE/8v\r\n=4vY/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDGfpTAtxc5aYh/3B8EoX5acbhw7qWE40H3BrQHDkrpGAIhAKPXMYhs0zdDmQ9urFQIhUPqBVqPMhzA6sR6qBb85Oyv"}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.92-alpha.1_1616584439270_0.9725151941657046"},"_hasShrinkwrap":false},"0.12.92-alpha.2":{"name":"teambition-sdk","version":"0.12.92-alpha.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.92-alpha.2","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-mOboJWpHmzL8GefAZQpa5gTcP7WZtniiDrMqnweFVFWAGDNWY7DKifZDvZzl7+70Cpa8HEEO256/+6jiD5UuWw==","shasum":"0385b344393fcd8570df2e9c82a9c72e066bf4ec","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.92-alpha.2.tgz","fileCount":518,"unpackedSize":1076219,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgXEkjCRA9TVsSAnZWagAAgfQP/0sZUSxTBXfhJcGw2D0B\n/jCMWYjVXZwuiG2G3CXgHEGuxatEe30FxT7XpgjcIeIYxTjpro/r/fzbGIyR\nPNwvBn1Pau/OnwA+471CxBd5/7dV4PC5bpcWtSepB7e3lP9NuJW/b1wqcXfz\nHh24evIy09H44i0a8kf6Lk9rTPzHC84j3kxiJng+qA+qiSrl1AwB3spgGF2+\n3VoOM7WNFVNF+gf2HWBs6aUhnvBOwc44wydv3OZbKh4YUbaflSavT2dMOwH+\niAzH+jTcx7k4PZtFmSFin4Sa+q+TlQMnMzN8ScfIK550UJd48Q54EQ3SImHy\nghz2XoA0j5MESow2E8a5ZIhSTGK/qQcFD35fb13KPLSCces79TIi1gGJsrR/\nP/2l96diHGPeIyyMTpBkr3/IKCMbI3tS89X646/oT4k9NcLz0ykKEkFowQO6\nUfvWDPayVF+d6qIDT6A7L7WnZjxgEs1Mb4kHvMUgKTYL0hWEl0btVWFmnNYa\nD+iybznp8ULR/8SMmBiyOpSmff9Gpa1umLh/35/qwqLC9yphr5HvE3T5EygG\nl88ECSo5S/pH/4Mewn7DoZIVeq9NKsiAdd92t9OBiSF1xXcM1L4pONay2pgx\nKEqhSnCGjSrb8bNPAt1Skp+PwmtKip56R2nvfiXSt2DARssn/4QjQcNAc726\n+9yx\r\n=f4nl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCsa3U4pWXMFLMPBG6ze+KpEb0nos84/WoDytryzOgq5AIhAKugMC7BdbmDL0vPZUeTMKSzFlLJ01hYa3pGVqhreaEe"}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.92-alpha.2_1616660770255_0.36306256401062575"},"_hasShrinkwrap":false},"0.12.91-alpha.18":{"name":"teambition-sdk","version":"0.12.91-alpha.18","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.18","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-6q09aeOVwLDrWhYsvRV5q4yRSJaPZzw/gKSkGY7dngeIWexYEyMTQkEvwz4nE+Eqp5iI0mKV+QEunmh/6vOvZw==","shasum":"6aaf4690a9bf792f606fafaa33bd9e9c5ba5604f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.18.tgz","fileCount":518,"unpackedSize":1077988,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJga8+ZCRA9TVsSAnZWagAAlY0P/0/h3A4tLprlZLp3t4Zc\nnbSwlCEjUuM+GDmNhHuhQlMMJ8yB+Qcr22os+wLOuJtV1zs94tjXZoJU4G3Y\nxgVxIUzaitKl9gL94hg/vR1KAWZVkGdjeat3EIfG65U2vwUYhVf38+eJMayT\nu4KSL2kel8ahFgP5KWFCx1JrS4UaDdHHXat6W4ZwfdttJK+BaZ3dSX3qWT5+\nbETVuHwOcjQlFwwfzXW06VUtseMd4gF9vVKsD9reVG207sbU6QXLdIhUs8Bi\nTrRNpsx9S9fmrGaLJHfwKwwiiKGim6l2ZRIwOi0bUcZmBvGX+3U0huCrfI/f\nr9aCXI9aOP7VK5iutgG7jXPvMFnRaBrsqvzhOsVU0G+V8Vmi6IKqm3nX0ICw\nnTuvEk2McgTkciM6bHJqWlJIHJ+75GUXdSS3+edF+86Nav034xtTlN+WupQb\nAwlt4HmQ0ng2RFbRtuIOW/aKnutp9q/2NHQeu257ZzwPVQ62Yat5HhMnKgd1\nP7VXAJiU9ryCtiY9v4WttSYucgVIOuin7P6x2HixQEw0WNfh+BcH/zCUVXdj\nxcz5LcUovbKwvznhRqxm9abalK7gXSImKklfQt1k3m0FFVKH80GL5sIzZFoC\nN8fIsBfACD/3Nj+anNACxlWeRwQC9XzDVZycuEWRW6nxL9GsyltpyPlUi+bZ\nKC0w\r\n=wAGb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCPUXpaGe6OjaX7wMHzF+j0AjdH6b6QObkF0Qezi6pQKAIhANst3PoRFXO8GQj3u+1eMGkQKM1iDAPK4StbcxqOqRgV"}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.18_1617678232555_0.061370786077850736"},"_hasShrinkwrap":false},"0.12.91-alpha.19":{"name":"teambition-sdk","version":"0.12.91-alpha.19","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.19","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-FtjH85K5IBsLUpu9BfilN1Kv1p2IpKuG7kY0KaTMmiZXDx/QF2bN59fRL33lFfFg3U1bDt8WMbpibN+2neYk7A==","shasum":"ead38495018d3736b78f38d77957a90130b401c9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.19.tgz","fileCount":518,"unpackedSize":1077990,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJga9XJCRA9TVsSAnZWagAAC3cP/139P2KbDwknvSAh4Zrm\nt3NDvyrwwQuPUwGLqIZ1nd7y367Yi+JmwBROI8BVYOYlTwSvktdT578LCPc4\nco9c7lSpb2zGEUI6rgF78fsVtI12xdJfJxicf8vkgF2DQoZP39rN/1fBa5Xl\nmWkKBda821odiodYKYE6FuquLeNlP4435d1HZqXzueIXMmMBIeJoCJAXnRNT\n7eD+5TSg8x5Zk6YaVbc9biGbJMElEW7iCy9VMK5UYcaNByIUfGYlpOD5KoyH\nWgbAZxuixD+FzzoUtIjuXNOgDnDk2s9VDFskJ0KhXC/2SEygehpwXzjNIUaD\nNkETLXeU+q22c/SyBTuQE3xMmwSNIAW713gA24Nf2P4I+zWDsLf3PJNtN/1a\n2DXmvj3ZD4l6rKUWGJP5CIzdevzEWPd/XEcHziDBOF6PNWf+OkW6o2rFxxzB\nPaGeBMCknz7YrxLxMazIlgKDOU2RL1s/QukU3SEOqX1NakYhCsSBk4FVbXUO\nfXvOGQj/ZjTWpBzpL9iVBO+uDfg4SJozo93/Sj/7p+K3cpQXfqkd3sJzNSqg\ncVSW7x49pYy2qeRE+O4LQzcnq4889frYVTppQviXUEVLPJ3GnKJymMU5VGai\ngQ0WSQudh+kS+b3BPtfpUlFgxPYVyLtHo0EPC7Pi4TT3oVoPy8rmwuxVMTK5\n316I\r\n=BXoO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBlHrtCsLNws5IBEEaRctSmGBVRHhe94PbTkMDFh1i2IAiBHI7Wvor2ZSLpKuH+zpbLQzN2eY7KtpVZKucLUgUJI1Q=="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.19_1617679817046_0.2432065724958341"},"_hasShrinkwrap":false},"0.12.91-alpha.20":{"name":"teambition-sdk","version":"0.12.91-alpha.20","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.91-alpha.20","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-y8+Oh+zfdjbfmXv7yty4woTE244hf6QNz2e23jejmFiwMW8YfpKBz+ObI2FlHPlJ1th6gxWZE2PY0hTsKOFcbA==","shasum":"8bd4ab00ed8b3bae672cb0de889ddedad9a2a33b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.91-alpha.20.tgz","fileCount":518,"unpackedSize":1078270,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgbs6wCRA9TVsSAnZWagAAZQQP/jNwg+ALDpLYF3JDI7ZX\n+XPpuro2kWGGguKkD9mhK1tkENvo7LrCj0qn+qgooqkMmiqHfBOeXmHNpfWH\nyH4TIzF2GcLmunXGn89LyzldpdbYjc8vFEjzpcTPpHjhJ6EZJJh4q0cjxsUI\nF/w7zkx2qkjaTgRZ7VuNrNM+iuRFnq5TFY9ITrTjclNiLQovFUnZEUkPJyrX\nKlZU/KkYZWY5ecPXafNE20Gp24EIBVk4EQBr9DeZG5WZm0L181cDLtw3FlFy\nzKNRKqb1QimR8xCbOafIMJ7x6RhYm47VFwQlM1OHlLxYFgRMvuU09DVwtwtw\nBr+vA7ipL8BxSEFmyyePjJh/d2Y1EBIvT0GInlxl4x3WUGZZdnZtkJSabD+0\ntqRh+i4smB4RZ71/7NeyOy6K81mqpjMScne4o5cjNj/+lKzATaM5ras0adaK\nWyuSosdg735fKnU3yBc9hJydPdugflOCGNfm+QPbQxWuC3Ugj9i6QO23SLlz\nNoH0pw61KEDqbt7PbB46E5NBLWEYpz8QuGx1LcxogREDLrtVTwJa2TDh5J3Z\n1jg09ArrMFIsmmFhOM5mU+zmmo2/BaxYSs0X44oANheqI9Or3+Ok3LbtkbsP\n9IRyqWzjtcZ89/R1CKr6J0EYSoCju6S1X+6pxOMB2z8c90ycg0L3qPtFIOSw\n9+zN\r\n=aKaR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFSzNp+lrAUJvndio9noUJjWd4xt5nXb+joKspSRRg4TAiEAuMGHXKvqx0u3v9syA9wcR2hJmnTUfBEWhG/ebNFt3cw="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.91-alpha.20_1617874607737_0.7887243486764739"},"_hasShrinkwrap":false},"0.12.92-alpha.3":{"name":"teambition-sdk","version":"0.12.92-alpha.3","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.92-alpha.3","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-BIo+HqwGrBTsiKwIaEVrUHLzjCL3nX37Ut+Ae683OVWoWpUU4tc3joKx27PE11trTX3poQDdi/T95gLrr8Coxw==","shasum":"8380ac0ab9c26b36996afe94751fbd169885063b","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.92-alpha.3.tgz","fileCount":518,"unpackedSize":1079903,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgdlVuCRA9TVsSAnZWagAAkQ8P/0FvRVCIiXrKUmYlIjLV\nDE9sn+j/ajKlRdd967+h2vJcSFCOag8osWTFv5UiFpQTuGXHNc2UhTmFmAZA\nPfnzCrOwqu3EE8Yp2VhF3lcg9L2vV+JvhigrHaXtJWrJuDjAaLfzoxynKbP1\n8SqudSi3eYvhNwqgk3uaEg5gkjQfzTHqKoEDyRsoC8sBYMcwzvrQQ6NfJe84\nagsNjb3sem33qlZjclevIN3r4VTNvHTe3VYj9aG0V7hvIqpFRP6kHvDdpb31\nYPoyRMS81U6vbyT9229WTAXwZULKiZwMHCBcE6cx6V064DClev4NQNpVfl74\ncI84rrPO23J2p1E+Yp/VtUPfaEtCRCQ/bd/ecxDCpxNNVLUQyF4dGmACl5nw\nEZMi1+7KVWbg+pcrHQxWniQxgCnszsr0v9I2Cp5o5+deB1F8i1v5wLe27BoE\nR1U0km+/T/BU0ivo24hb24VkRt5kEZQIbnue0uxHoGwiiNKcNIep2B5RTVVO\nI6Dpezvhu5D0yuwdtL4dmMwfZVyCMrfyequSv3TyREXh0Ovu+FC/pGepp/m9\nHR1UUdZAMFHUJPibwgItXV2VACxhGdB12pcRg8bAagFLN+Lqr7fXV6ppdycK\nLs1tG9yWgzXXVp1AUsH8XbOw/+0pqbAyZxtWBuywc7r8JfIo6IkVzb8LNk7r\n1FSG\r\n=CjQn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD5Dnf/BCmWXrqYLqTchsOvDSWYE3jGMmokNq/98FeSfAIgSI0CBE9+vkAL8ESgRRDtzFFA3Gs+hUpgZfZfUBvn6bw="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.92-alpha.3_1618367854003_0.26961891585643505"},"_hasShrinkwrap":false},"0.12.92-alpha.4":{"name":"teambition-sdk","version":"0.12.92-alpha.4","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.92-alpha.4","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-pC2mmbkoOIPbxlm2nRc5ep3MUx2pGQTEGpEiLHO2/mGJhd2vU2rPnXd6EBF42bIMxGWfQ9OZ2o2q6M8zAvjvOA==","shasum":"da721240d42df55f0e0b29566c0fa9269ccc7dec","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.92-alpha.4.tgz","fileCount":518,"unpackedSize":1080282,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgiVS7CRA9TVsSAnZWagAAaOIP/jBNV9lLntv4DrccFXhr\nf2134iqWy/b1Qo5zBWgWdeSf3b58gru8TIzvn7bTYqQ4JEXOY5v82h180lFk\nI0biPPttzeASZKheNchx341HqQ+cGKBkKl6gwa0GmN89VbmP6uy3bll5t0sV\nf09sB28VH0+IsJUVMe1RWDlmVj2NxtRJVc2dVZvW4TwwjAPHJGGoTHyCM9um\nDkxOukelmNEZHhVp3yIWCSKYlevxNN/AE9xV5qXicbXwetQ2i9Et1y9RYgIC\noWTC0bZCXpnX8Z8nTqK4H6nXmw8oBMtwee2cv7LSd+6u0HcSP1irxY0LEXM4\nRkm3dUOivwV8ca+KyRzs+g6PMUVDhtRU9SN2+3xXdEdydwCFbLCOvAAT8fPN\nQXwerw44sQWxZojoPYwhPhFxaBv2tvU9N2mb9hy9savVKBHAolnXPV8/SniJ\nHYm7ECe2R2rthu01Y7pdILFT1sF1t6YXEs+K/bm8AuVs5nbddcoFDMof2P84\nZnBEKfotoQYgfRHLuYK8oVHem26Ja+HZm9g6S0L7dswhFgMPRgXMdqwTVBvC\n4Qp/3JNflmcDx/TZZOQqn4IZirgmp3nMhGBH4zQbpFTTTuz3lCZp5nsxcdaK\njUJec9NzLKiwrGNZMn1AMvVJCV0UsGv0N/sG65dVxlZ4YjgS/9kIR2hl5S83\nO4MP\r\n=o9IA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCGEWRVKds8BIhUDwzX5H8e7ThEcHwHly0AXTcoZtm26wIgMEmnC2HHb583iLb6APTlu0BcyM4YkTX/ofsUA6Yrh/U="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.92-alpha.4_1619612859018_0.4478397269845793"},"_hasShrinkwrap":false},"0.12.92-alpha.5":{"name":"teambition-sdk","version":"0.12.92-alpha.5","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.92-alpha.5","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-sw7aaO0f0LpSrPCqtl/sNk2HuTZ63r4PjWT0zbK0pqVrE6CcQaMVZhUBSTBzaPZIITbIxnURw5uatB2dNpjHng==","shasum":"b014bc612efa6bd9850b3529afb837c2ddd5131f","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.92-alpha.5.tgz","fileCount":521,"unpackedSize":1098281,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgi6P5CRA9TVsSAnZWagAAD98QAKEAkMPKivPrn1cjg7Cd\nnvXl+gkcrzyiRLt87RkDQj8nO2GneEVOXhXRir8BmsITleKBAwnsVMD0X5oV\n1WwD0p5nHwfilG5szPfSMb/JCq/a7l2V1h0raTI6OZOpfwAI4EtbzDudzr83\n6PV/vHKjBpOF9ZhZ+EiDuE6mhxT0kPPQAXZRABWkdfEVKvVQgLfKGhUEGQ/Q\nv/kf72QZmPzaoKGCOJMIRfkgfOjYW4O7r5KWQTxCzGu7nTgiY0RD+plKKuon\nA/PKwMRBkQGvFM6ds4ZuH6piH2YLNQ/60x6jWV4OlvDjnshx1e+203d9GWPM\nOZ73Zhv2C9cubdFy2DLUWN0XBjEu80Wvjo4Yr4NONzkVajto9gOCucx64Ir5\nwRva6Ny1zc0pGZF+Wd2jAT1oL2JN7C3f/K+RlQlnhg5+zvZMeyMBOW/Q9QfH\nmEZ/GHxa4ujD0zWLh9d/p3hPd/deeVkIh1YhvmgRX5mCuK5o0dXYrJBBBCkn\nab5PjET4zQ3FF+8DwkqHC5MTMz6gpPO9+FnPjpBAUuyM//VHxCTljvRhfbh2\nKV2KSqePdYb+fH1KxpOdaOznzzSE1Lw8uo5KDs8uM9+Aqo9f+wX97FLUhGaH\nnrcfITQ+13Sf09uONo2ICjKPE+sC0t9MqcT8L34zPl+Yw0fFzjYNR45HABwm\nsrwl\r\n=pJIu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDsH6WaTmm9umASBjE1kEokP6d8894Vg1s1/lCIa5r6HQIgRVB0lHlOwlPzDt8WvWkVn1KeIPla+VXQDnnvZaVs93U="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.92-alpha.5_1619764216979_0.36052044954308404"},"_hasShrinkwrap":false},"0.12.92-alpha.6":{"name":"teambition-sdk","version":"0.12.92-alpha.6","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.92-alpha.6","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-Qhy8lFVmSGHNJU28r95ij74TYVjTDgCndwv9REbLYWUkRVWPht9eA/DDreLvgP0H2zX/6HAfg8DDCZ8A6eWmvg==","shasum":"566b8cd1274a604b33e023840c412fbf42ca6699","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.92-alpha.6.tgz","fileCount":521,"unpackedSize":1098523,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgi7MZCRA9TVsSAnZWagAAL+YP/iD9P4z4L785UZNlXzbK\nJjUZmDj+yqJ4Y5dGlwB489hGi8eqnmQkSQg+e4sSJRTCmHabgYuJUEn/dR+Y\nQejX4T1qtLjarHmpWkvWT5stIVW18VosuaQXu6cLyKvehxSk9vCrA8qzDPE0\n7Ch685zrWwUlgLUJ1cLyY3nmli3tb9KBnLmnGd1ePqPPlJr7DlWl65BvOwE0\n0iFtSWXLacz528qmRto9Go7tyoaaGEVKzrXIOn1zTsJYmKWUg91MP50D244Z\nJsrU4erGnyr04gx9blsvHyDp73AnkXBJ+f8H6CUPssKmF3nh04p8vT6/oQS3\nq8r37zjheKHv6CmvFhX4e22mFfY2kptt5c2iD+xBKWosOOc38EMjBLCjAS8n\n2IQu4jmvlq2InxLxuk7AQejlvd1jd3a8blrZEqqWsg1VB5dAhI+V+qWg0T1j\n+FL1BfR6VGo4j6nUaIW+R0mss0T/NsBxLAzbeSfKlwQV1SIzygGzW4QjQfl3\nURmc2Boxof8ak8tAd2JbKsc615r6Nm3x3EF4A63Rpce0ISg33hh3Xiy6uGf5\nmjKLW+8YZ8NBkh93MpLsTW8rYEtRcy8ml9F04X0qecMjWTks4A2CygN3MRKH\n4sGVxbT8QIEFz0YPAbUe9q2etlHsFxLEx4eewWIgGTL4OGfz32CWb1dxgado\nJHKR\r\n=jGXL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB0yU8vEhJWYIQ4b8bU8RFVTxT8KBbC7UgYF0xxZIj/OAiEAnkgAhQC1GiXtHVZe6shtrxx62AVSwZA4HEoeltrfffI="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.92-alpha.6_1619768089055_0.860241756436261"},"_hasShrinkwrap":false},"0.12.92-alpha.3-sunburst":{"name":"teambition-sdk","version":"0.12.92-alpha.3-sunburst","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.92-alpha.3-sunburst","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-gCUQO0N0zzw7ErYIHQHiEaWYXVeI050bLzPLL4UmKGd+q74tnhu74nIoGiP6ahc22Fo9vMt4mAkqgkj0Fc6SdA==","shasum":"979f5ef820aae49dd450e088038db268f56e7598","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.92-alpha.3-sunburst.tgz","fileCount":518,"unpackedSize":1077285,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJglK3TCRA9TVsSAnZWagAAQh4QAJ89jIW2an4vfppQhX+T\nsAUNTwPmiBw5mmZavN5Gv7RBjwd51EL6xXv+CgsEZJhEgf1gvJN3D3+ujnVd\nya5ztSOaRnvwxB6lvz2argvqmuZa4dIMbYYl6BnsIWjlNhMqK9jAMX9I/Q67\nnXZyFUxiDe1o3DTTSZH30mNV5vQgyd0+oLszFyhhtXHYSQCfNfa/bx1AalZh\noACvQgYe88nk60buG0fzYiyO0270XMIoSkwuvYKdPScai4U8Yah8kR/8Euql\nGxQP89lIOuzVmVbB4F55KPKDRpANKkiTfA/PibMWd9KHmgWUynA780SMBO+e\nicVlESYwluov9FJHpAYwZfSOsCWxqwsoE+dkgPLd6zrIAWMhaFJnG8RcgbCx\nU1eE6v6hZFT4CpOM1B4iBlSWxWIu16RS/jOstE6g8ruqObVakRAr/Noip7Be\nrkoPMxywU6QWbIcpb/vEEg72bGvhgehKhR0ojQgtCOZxeTiMCDSWZYM/A26W\nfEmmQ4X3J/0JN3MH5Wc1X71ckBUikAomXaBpCqsPzpqI5EyWl62Ha6XNXIBd\n3cJPiphIucpfLwjHHg/djFhj2sfX/iKet08oE7RsIV4Apj5YHAYpTza1anA2\nBJNgSdGV9idb4mFMuuXMRWMiO/cUC8owd7/TqwI7iD8lRWk0SOSfXlSBJK3t\nAMTz\r\n=m2Og\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDLBwhutffAFd/eMPhdUuiFQFmklB1xFRFkhH3uMhLM/wIhAN6uIiMeN1kOwvuc2UV2aVq7B7R3A8PMWQYwPm6BfFp9"}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.92-alpha.3-sunburst_1620356562422_0.887147681743494"},"_hasShrinkwrap":false},"0.12.92-alpha.4-sunburst":{"name":"teambition-sdk","version":"0.12.92-alpha.4-sunburst","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.92-alpha.4-sunburst","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-LslC7BW8KOLCmle6RWwVTuTdPbpf1J9qXch9QvS5VfdzZIoO9nexiAaL5FFy8qRgxBMZmiIU1hFwZirs8fIdsg==","shasum":"eeeea2ae405cc1ea3734b587b5d49e53ffa0a008","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.92-alpha.4-sunburst.tgz","fileCount":518,"unpackedSize":1076607,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJglLVKCRA9TVsSAnZWagAAHyoP/RJyKNBv3pKrCDvMgZCd\nNbzn7WGp+SNGnNXzzeupEl7601xMgDFQmXqUghg4fwtu1l+TYCrhRDhp4y7x\nW+UkOdwE6PoMkreHY0rueKT4GABSyYlZGvI7uEf6tpOazjOqeTnnaNVmVpss\nNTpCg4bFMF9Fd/NUfOJzbhE4waX/mE04S5mURrkhVa+JyCRUHgTxo4YZbx21\nPjemOArI5bKNORq8T84vxrVYuikyDzoAbhTQmTIUv4OBaPc6XnshKMLGwRez\nTFvjtaam8WbmG/5DZQyxc6dnhi3jOORcbb5FtRCSnndeq+sY+HHaj9/RTVuR\n6Q6VAjXFxPUBrkNaY2ND1i8sA+ZVYOnyFcrv2Gkz7+/950wY6Rusp9747spI\nxSyXTLCD9bp0WcIuoOKNY2Mi32MpzBb/ZzpuGktRhs0cugBkvX6zi7rEI036\nrWyRu2w82BNxRAmZ0IBXQXIkEXHA+y3XCYzjygZNINU4g6SqX7Y5STHHcRWC\nQSdsIbKIVnaTQhVBW8dd1lX3/dBqWdo0T7TbefXo3VeKWc4t5vEP9hCOTlsn\npcQ9SKS5jRfXtGNVDQA0vl30UCEmXkNEZbntfutxUQSLpToYFGhxCGM/7Fy4\nVDycDLhp+0h170jDcyyke+aS0l3PKTW2wjUHoVeyAKv6Uo1WS74r43sfVMWt\nO00Y\r\n=lByT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAkVrb9IDP4nMOMWRD24DN70hvxJh5yRdgyWztFfdCfWAiEAlGGjIP6Gp7ShILJl7QKQlzkaxVdrDrLtWPF0Yz05wfM="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.92-alpha.4-sunburst_1620358474260_0.8417720972434621"},"_hasShrinkwrap":false},"0.12.92":{"name":"teambition-sdk","version":"0.12.92","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.92","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-qZM61ctCLrpySDadgDMSV2jqWuHbO17azfvHDB++xxodEt7eTFrj9vxjE97w6cj0umEzWVqR8uBqyG7GVJO22g==","shasum":"84507add336c8a59e267623ce51a5b13899a5925","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.92.tgz","fileCount":518,"unpackedSize":1079609,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmNCMCRA9TVsSAnZWagAAc00P/0c6pcyN2YXUQM9ms+Yo\nQpMGdsqiKKYmUMxeTQAv0Iopr+lS52/vAmQY7IGnXC34p4X2Y96mR8RTsASG\nt6LH/ciFtNKF1rL6KtdgiDmIVU+nxN+clBfCSaUEl/SPt+1LtZUsphfwOxM+\ngOUScenecn2VOORQ2ZXeF/pqEta/wwnvbTU6NoD7QRnWApHLTQ4h1DTD6JEt\nO5nHZ0BdCswtqyEQ14PUHwJEjDsCgoUH5YX9QIR1R1SrcBIt2GYYIbSWc5OP\nR1i6irk41y6aAqzLR6Xk8TdQBOLz6j0nz537rxae1o32BjE/ocpDbhCggOOZ\nfKTTZTfOBplNXYEQc89CoJ7qZ5o42EtX58wVbSZlC+7OgWOgAIFZuPmI9axY\n3KPHw7/6mJxPa3lH/jqnoZ9b3/R2VfqNWHUSs7fvnjIYS9+4kw2ZviOWhAjN\nE7Y3PlOrc7eUAtUYIPi0DMVFE1BOAZXAeISkKVueulnur/sDFQFLCm/0h/Co\n7ba6toidZr8wQRNxBGo7dXXWInKgLmv/BJdwsxlgbUgjSAyZLDfqq29BZVrE\nuF2cgqkUULy3K7GlB4iMNy40as7/99z7BMOFtsVXHkkDeIcI1fmkg0chWVxD\ndV6hfcMqkKmRBP0y5cOSuBu8FrFCR+4W8h8puV4TT6VmVcPqgJWKo5xrnyPV\nYoNX\r\n=yB1I\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCzmUSflkkCk2BjKehnfPx98Re52VO0j6uI9sHIjNIf0gIgPWB9HIvfJ3Hj3M2lDePoWEamGvtH4CfvY9DIYm6qKoM="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.92_1620627595501_0.5979259941369577"},"_hasShrinkwrap":false},"0.12.93-alpha.0":{"name":"teambition-sdk","version":"0.12.93-alpha.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.93-alpha.0","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-QmyGQy8FNQIzGTOf63CunsjGAephp/YHZ8YDuaEkZ5DIwGwxHhFTa8M2xZr9u1vWCOXBtov33UJ8qW/6ZBmeig==","shasum":"35bd35ec9437da51584ca53294ada5c6df44735e","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.93-alpha.0.tgz","fileCount":521,"unpackedSize":1098237,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmRvlCRA9TVsSAnZWagAAN7gP/Asd8QqZOLKS8fFSBqgP\n6Q5FCFdodBkVAcOsgTg/zVfgBNVZhZtmmdPTeaovyxjtkrORjieLH+7VwC4t\nU99RFj/mwXspx+bUno8LgNnE4WTX6Mh8GncV5GihrF1rgF0cLs2sKnJxEzCX\nMKXeTPzFi0BPGFN0jN+FLR4bwb7ppi3KZYZDSXBPGyh+jEJn6fcQ+7kzDqWt\nnhDf+EIOxqU6KGOEv3WOKJ5iBd4CR9p3l/I+iv9ZA161SVIOML9SJCgD8Q0U\nDasPsOIy4A63eWUCkp3MouPeVuS5r2pviAyKZwOsd+Z26afUKVfp5RaY3/1j\n+h3Vz73YLpNrw03c8F5JwWdrZoUqftIOjq8Fsy/dpQvzcxpns+uTJ8WBbMuh\nFu+An1PLubaE0s1T0lHEMeb2I/2m0OaAa/QKL7ZqZijEdHP7ygqneIxXPXT9\ntc1V2PpyRlnMJRTS9ThQAh5wkUZyvu5MkypMVCxbygnSSfVczen8HcADDbr1\n0IsSxRkthx7W9TbK5TOWhL72Koi2hGYvR0nVmx9KnvibVGlYSgjM0i6/0qxY\nEwhUh12BQ2iELnA9046UF0rj7KLzHiJy6xJ0YNpuzIh7YfUQzyEYzWbjd96r\n7pPcY6rfrjFP/hUCf+DfSe3GRvDY5PpB0jbQ5Hmg7eqC2whOAhIKqj/mtI7x\ny/ii\r\n=9Wr/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF+1aLh4ktU/ExwxUdB1QXHcufR6g8Hvcvi/eXiq1/gDAiEAgJYBIl52fq8o2RwnuGx+XlgoJzSwRtVvaq1J/uKVyjg="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.93-alpha.0_1620646885137_0.917953336219099"},"_hasShrinkwrap":false},"0.12.93-alpha.1":{"name":"teambition-sdk","version":"0.12.93-alpha.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.93-alpha.1","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-KyJ5Y6U3h3lD9i3Je1MCBUhJT7zhl4LzazmAlQOHtlKFQUBzu12VEMf9VON0S7IQaggzAMqDhxU09uplX0zq2g==","shasum":"051983fb43bea76ad6db62fd4a9fdbd4828fe4b1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.93-alpha.1.tgz","fileCount":521,"unpackedSize":1101704,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgp4F6CRA9TVsSAnZWagAAQYAQAJyOcTjARcrLqzel77wm\nCsGZD7CNcImtAW0Cwa//gfnDJT5qhWdQllvlLVuVJ3Sp0gtqPTNILidssODQ\n7umw6A0dECkNOabETVhQLh1j9HYB5zF7TrBR6uSPN+p+rrkh0VDVZlyFV6mx\nxlk7IQ/2nWyTONU+otjrWBHKl0PIKYM1+5/7GAsaYK9VbeAdimN+TqC1cYaV\n21NKh3Obrv8Jhx8OFy4ohMuZebm0MqR5OJG3+ddwVucOz17lmHkS+266XIXZ\n658AybM+rga/LjZ/VMQdiiGO+YiZNJu49US067kT1WEeKe934fmcdJ2J3D9Z\nXvAxbVCJlU7BvZ50Z63ZwGWCBohW1qAKdAoVrs9ebJYpODbLVDTlCIfANfq8\nfqAdPlCzD0+3beelpCp92gQodIpGU0VTP+r9e2sBGisXDEm+3jl5lfTBXEFo\n2LxiTGXBvSrpznT700PdkaNARQr+GuqCixNDf8r+4dzPfSRM8oouMl/wia5B\nIC4aEmwykz7hjjmzlE0hbD4DQaZnW0Lxy9OUFNL9svIf2kMLFTCLhFpkh5gU\noU2tk/AOPwVJNOloYvKlhQO03cr74QAuQhkUKu0fk1rLCqarbOFKjaVDDgI9\npm4YQoPjh9X64lbpZII8xgbxT5QToMIfYLNjc0BitxuqmGTDeEuzLnjoodEj\n3Arf\r\n=F6kL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIARXmAPV6o5+wfHGJ0hnygEV+qHBx3h57lidur+vBIIVAiEApnA5BAN1z/iZwu3AO4sswDYrMC9G0oHclFUN21sTumo="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.93-alpha.1_1621590393887_0.06441215656300514"},"_hasShrinkwrap":false},"0.12.93-alpha.2":{"name":"teambition-sdk","version":"0.12.93-alpha.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n\n## publish script\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.93-alpha.2","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-4PriQ6PThS74Oahb+f170x94Qrm+UCHTrT2qUE0FRvfXNXSrD1NK4bVYC3AmTj7D9bKIoV6pW63T18qxYvWjdA==","shasum":"10fe73b9492c5b2c68ea1cff9a3a2e1da28253f6","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.93-alpha.2.tgz","fileCount":521,"unpackedSize":1103877,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgp6IDCRA9TVsSAnZWagAAGFcP/jLRt0DlRROLFr55/GsC\nJZE3bxy5J6DB0QJLprcKos0+IrAaBq+GKMTAhHeoxCRz2NIbip5R7yPHvexm\nSR8NpofyUAOdDJ0V7mPKFPgMwdMWIm/d7eV4sf+hgSJzcrTnrmQc+m/ZKUhx\nMe97XTNqmyGpy337jciHdw5W4mE69Zr1Zj4Akb3bWUgZ5+S2hb5aN6lRnDHG\nux3wcrgir4c2zRRYaoLVp573yJFQUhOY60We3mqUHnEdJY9HNkZ7NniArqIZ\no8eI7st4eBW6NaNjC9AeoCNoR1nKJ04B0GHfFIwOuDiaf5OofABpDMdGrICC\ntvH3n0WQ1pxkY7e7su+iF8FsFnSfjzavQYU9Tdj1lXEmslrG8dIiG0HeAyr5\n5WGClvnrArQPeswktg0VFCaG/x//RHrAqQhZEZUytW4AwW1zhiBbiY7icLfG\nOUivAGY0ZW1UMB+R3RCRqn1s2aVGhMPTKAxEcCx+tlzVK1RTVi2eTCi0cn/Z\ngn0+CONRt4qU27ReeQDxz7+EpOjVKQBavIc0sa8MhIgt/59M8hu9B+bOBThX\nTu1YGaN+zIpnAvImy6XLqlAucoGkCO+05xp9teRwDpPfs+AMqANFs/m8LR9p\n07+MALq013G1L2BKhrSivprc1GeR2vWl+usm2+7TGHuiNfq0at7pUGDU9OVM\ndjee\r\n=eUsr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCqrvu9sxa6jlmunchGH5WIZkJrbheE+wvVIl7Zkx1EvgIhAJ27gNhc6tSdOU5IQw3ZDmEOkZJK0s96dPOusm3nFqF+"}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.93-alpha.2_1621598723012_0.798027353381568"},"_hasShrinkwrap":false},"0.12.93":{"name":"teambition-sdk","version":"0.12.93","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.93","_nodeVersion":"10.22.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-xwS9lfvFUQ//lzWvzQc+uxx+p4KB+u0qPvhBO00N8oxqGySSKz8+NB0ssG4eY10wFnwGcagJ6rDjAET7LfjK7g==","shasum":"36dcefdbcb6fa166cd241795d0bae52ecf8a69e8","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.93.tgz","fileCount":521,"unpackedSize":1104655,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh2885CRA9TVsSAnZWagAALIMP/2WwFtb8TL44jcHNfNwP\nMIIQp5L9iAlqeq++46eT6umLIfTyY14wZyfUAFZN0UAnu3BRnn3CTXZve+QA\nBCkpDg0BQZ8wkcIOHvIlDwPWVam22BywZz04iVFi1mOLC9X0peNyC9acBRQQ\nvoAratOtuncYVX443EhMBrzDTWXBC8pTzOGcsws5bQsOARblgkdc9NpjPsEz\nUfW4zMkMGKN2Q4/y8BD8BrFMTKf1JWBpxCePVej4zPKBQz44QqWnQVJt2M9Q\nRJRWpYYTtzefQZiOj/8rmEC6jDyUo2f7tiSlrTCI/ujFL1k5wYSY/V/5hUis\n5bOj55/sRSV/ZPMzD1PxO+TwWEpDbu1uLxXlQToBb3sFx2Wef9YQVfRHLe8x\nPFqXjA+7JgSWr+GxX6u7jKBHrYWKUmKT0orjkd+QD6qYci+uwRJ8g0fFP3Tl\noMZfWjRajWcV6TuMRT7ocVU03/cQG3ffWblUUceXos2QdoKTA8Xt6r4CYCh8\n/n5+ughdTyQBibuWsoL/kTLj0CCIBVNWV67UPtRSCbnu9v4EfUkHIbTrH9fA\nAR7y++Lu+WvRQl04nMV6if8jl/PGhuupT+EJg41PPQ7toautqxP2lQYqfJdY\nwlonVmCbIwqRTJPptypSFTtOK/Sy6xYwQLpEmWeCDXSm1D3fJfsZ03nugUpM\n0zpX\r\n=3Xqz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAlTGmz1o/Q9fk/76RaBeYaCX+qHKZet++BjM9olVlISAiB/msM+wKbxu7RPIomFzb86SBBgiJHgbMP8tTIlttPujA=="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.93_1625123954572_0.5547501832889641"},"_hasShrinkwrap":false},"0.12.94-alpha.0":{"name":"teambition-sdk","version":"0.12.94-alpha.0","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 发布\n注意目前发布要求使用 NPM 二步验证，请参考[文档](https://docs.npmjs.com/configuring-two-factor-authentication#sending-a-one-time-password-from-the-command-line)，在发布命令后面跟随 `--otp=验证码`。\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.94-alpha.0","_nodeVersion":"12.22.1","_npmVersion":"6.14.12","dist":{"integrity":"sha512-hTuA1yC1vIbm1DZBUoAYji2Fn9LUFXoz9uaFwLl2rPQyFrI4KOAL7UX0OyfbBkJf4mpx/ARrjoErX1ZKcHtkTA==","shasum":"b2a9e250d8b0cc930d263b834accdff6e4d10f6a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.94-alpha.0.tgz","fileCount":518,"unpackedSize":1103771,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBEauqAob9NrZjzRNP5KyJZun873etTh+G13yv6WXp1NAiEA9UqfChX+/MFfXcATgmsTRskZ4GmrFWjgK3EKI4TKkM8="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.94-alpha.0_1633765010432_0.27291824382576135"},"_hasShrinkwrap":false},"0.12.94-alpha.1":{"name":"teambition-sdk","version":"0.12.94-alpha.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 发布\n注意目前发布要求使用 NPM 二步验证，请参考[文档](https://docs.npmjs.com/configuring-two-factor-authentication#sending-a-one-time-password-from-the-command-line)，在发布命令后面跟随 `--otp=验证码`。\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.94-alpha.1","_nodeVersion":"12.22.1","_npmVersion":"6.14.12","dist":{"integrity":"sha512-60WEoSRwTFq+4sMVAIXxatiy5r/H774NozXtHKkBqU5AnsCHVjW+suOdoGQMHTBwcKoykySvCrCZO4nKbHeUug==","shasum":"e4efb58d8a958dd78a550bbd28c590b646ff1ea9","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.94-alpha.1.tgz","fileCount":521,"unpackedSize":1104654,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH1Gc13GofGt0qAxgYg3lzPOfmxaiLf00NhaDXPJGiurAiAft0Wvc4lKM4FFRfB4oVOnWe0NFAZpsw/jwQZYG/eyqA=="}]},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"aicest","email":"nomailthis@yahoo.com"},{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.94-alpha.1_1633766933274_0.0276514786826918"},"_hasShrinkwrap":false},"0.12.94-alpha.2":{"name":"teambition-sdk","version":"0.12.94-alpha.2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 发布\n注意目前发布要求使用 NPM 二步验证，请参考[文档](https://docs.npmjs.com/configuring-two-factor-authentication#sending-a-one-time-password-from-the-command-line)，在发布命令后面跟随 `--otp=验证码`。\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.94-alpha.2","_nodeVersion":"12.22.7","_npmVersion":"6.14.15","dist":{"integrity":"sha512-aT0xE/BFsNGJSWXA+ekEGw11jd3iLKRt4eEwnjC66EPqtlJcgqoDt1YATgwKBjt12G9HCi0qsGn/uwlj1hfdBA==","shasum":"a0856891714652756d73c2d199b5239cfd4d56ae","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.94-alpha.2.tgz","fileCount":521,"unpackedSize":1104891,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDFzwrMJIrkXIG/HSDJIpzKnxL/5qHYz2qIBBvoeFkfUAiBkM/9NjEdS3+7ycC3Q2NvAIaNYjzC40FzNEmQX3cTWgw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiZ0J4ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo2XA//TRdS1BrgJ7mvJACPo4sXpTU+5XP8lLgptzEAzHCDuk0NPLV4\r\nsEtfF0ypN7Cr0aLVfe1L37Fy+oODfcz3BGrOHwIsF3QTNCMZOgCVKc5xbtVm\r\n5XzuQYrJBBngOKytkq5PUssWPuJBKfJiKBJG4f4vwKB02MitcTWX0vcGm01G\r\n01bTU/B3LBz/tyeSFlOFsNmUUiPuRX+ha+obLHfDW0KSN2Ss1/JPKyU+lLGw\r\nt96XIu2QhGBkII3MWYMCiO/GPMoc5jj0IdJsjaPv1Vd3lIz4CLmEtaB4Freg\r\niVie6TOJTq2d0i3rW2sGz4lwYbgJ8nelfcw8NbfaG+AmywGEaspe7vJj707y\r\nj+CVkItZzFULw5RzdLx1FPLP54W92qInmclR8TtOXGT3etZ85D0pmtDDiOyx\r\nYliaqXCzQsNMiA0Ssi9eH2nxYD5vEWhc1AL+iADLoJuytXAgCrxAaCPk9ZRY\r\nPSUm1z6+v3n9pXCuyG0UPw1NBizJbJV0+1NvxdGLwOXtsBqJKwAM3u1+vO8S\r\nbVpOkG5b+P5FkWM+6EwGURNk5JUu3FrfWFOUzLxcEcIyMKugAzmyEv3qzau+\r\nGEWZdtzqhXZi9DxlZjtk25n3rDyHOYTyWOdMZdQYCRNxRTd8FL2IHAd09Kly\r\nu1Mvz7cmpx2++VFYSBTMwJB9u5dsr38s0ig=\r\n=YoxS\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.94-alpha.2_1650934392502_0.7637360522127008"},"_hasShrinkwrap":false},"0.12.95-alpha.0-smartgroup":{"name":"teambition-sdk","version":"0.12.95-alpha.0-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 发布\n注意目前发布要求使用 NPM 二步验证，请参考[文档](https://docs.npmjs.com/configuring-two-factor-authentication#sending-a-one-time-password-from-the-command-line)，在发布命令后面跟随 `--otp=验证码`。\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.95-alpha.0-smartgroup","_nodeVersion":"12.22.7","_npmVersion":"6.14.15","dist":{"integrity":"sha512-rN4Ri3YKB2mYt6doSRHcheQPRWYwFHXmBjqHvqedRJGw0khU4SAB2EzBF+27Nw/fnAcLacAQCkgoIqbo5a977Q==","shasum":"84538f43cd504605b70a2b10f8ad0f84a89d92f2","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.95-alpha.0-smartgroup.tgz","fileCount":521,"unpackedSize":1105145,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDvs7FKHCu3Zdu8jeE06Qcr3zr97KfCo0fAkc6NX20LVQIhAP9mtXtX52IeGxPJhst4zAesookOlFBL8aSMln0t5Piu"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJioJMJACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmopdxAAhPWtQZOwnCb1j7IsvjqIsejCVidODTOPy41EmSv1d7qBFQKC\r\nDJ0aEeLlcULEb/e9nqX/9ke8CMGURebuMxPkKOQ7Cr63d0u2K96Kt3Si1N23\r\n5JIsVtxEAGu5KfUJIg0DodFYxKiXabTl6rM8kHZl2BUuSXJrvGwljD/+q8CZ\r\nKHeHw6MmvQ2JE42l04LjeU1/b4EW47y76jFsr4TrS/Zq5Wgp9wbUIXQ8vGsO\r\nMT1yL7xJbJ0pDhCwZ3EMCUNLbxA3TNpi5NIt2+X9/Vv8DukImn0O+h3MI+1W\r\noMb3uyPAnI6+eWOCGia7JfgbPXBWTgsKv4xihSDADCttGzQOvogxsJOGRbl/\r\n7z6U0qcy3NQhfxjR7c3TiatG0SugImyC/QQT4eg2Z7PzpcBffx+umseLyhAk\r\nbR2qOsqOR3SSZbrmxyemjx+LfeQWJ0WZV/CcwNgWGy3BoAvlBZZe23mDnGGE\r\nDzXaauo4FarziI++GjNwQLJerIXJkDyJBqoVM+lke+RhuhWciW2YvCSjMAaS\r\nHHDCaMaTqyGHdOWqWN2WhDUGW0MARrJDvLt3vPwOfwvIlsCct6gQjnmse3xB\r\nUoRYlTzi34qkRJpHxAIXOFmp8DXvEsvt1DFCDe+7EZzWOdpQeZnKuLn474us\r\nmxiaNZorAeZEUnJeDea7LkWCK/uGXMOLfyU=\r\n=eI99\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.95-alpha.0-smartgroup_1654690569018_0.27906442100971085"},"_hasShrinkwrap":false},"0.12.95-alpha.1-smartgroup":{"name":"teambition-sdk","version":"0.12.95-alpha.1-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 发布\n注意目前发布要求使用 NPM 二步验证，请参考[文档](https://docs.npmjs.com/configuring-two-factor-authentication#sending-a-one-time-password-from-the-command-line)，在发布命令后面跟随 `--otp=验证码`。\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.95-alpha.1-smartgroup","_nodeVersion":"12.22.7","_npmVersion":"6.14.15","dist":{"integrity":"sha512-G8oSWam9CE/NOu/RC2KIZ2nFkNy7pwrP9ctpLkQ7R1JkyqXqvqghqgwnrQ8J3BMMwC7bl/MZ5SvnENk01MIcpQ==","shasum":"5e5b8e9148cefb8a0016a21fbeac8066479ae627","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.95-alpha.1-smartgroup.tgz","fileCount":521,"unpackedSize":1104872,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD22SDP6myEyqj4LMt0yPAShEDiK6Mngz3mttkV9woh5AIhAMvBx6G0inQUVHec6SD9dPPspNrWf14/GKiX10psE65t"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJioai9ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqqww/5AZBaMNM2Vp+muuys+ZZCS10uAIcpHzyOjWyrn4KOMz25S63B\r\nhHXEdhqMO2S/nky+5HbLwjIb7uCJl4327x+qF2fjogADNg9WtDhrpA5ml72l\r\ntEPPcYrMRw00xuFxSIRiRD4Ji9ucwaalvnr+3GiDTy1xmz/+d0RLTreVhOuF\r\nzJBqWfKLfVxIT7S9ZBRhl9GctWgCvLc3TCFJO7OVECzUNE06AwWs6D7YSmmK\r\nLkrohr/FLPH6cMTm6U8cn3G15fcrlcVirPYevbUsDipHeUiT42g18wclXITN\r\n94vLPX1V0h7qbHuQLES3QmRDnClvNH7iAnFwLMq5nNLLFeHLGAb/QXrpaEz/\r\n3mCC8S69e2/TqxvmX23SCIGw2dQklzJFkEiShHOkmQYpK9Pe0wjQDeHYB+Jb\r\ngzNMCS4CEqN+SrsZWxnsMFst2fDztTWR8cF5Fbc/ycb7FwfCQR7orGI/izIO\r\nRcOJfmLtogTKjvVE38mj2j1Ln+8eZEZ/Yf83pjM7E8ElofGQl2PvTlCJ1m/b\r\npFF56j+fX4e04DYrlZLe/qze7y6t5sHZzz0YDns+ENDjgJBviMalHuZ3C93s\r\nofvXG6OlWZLJVZWsHGWIEcrWSKryi7yBU90ulPHXVgnh/kHFxhCAsuMFAhm4\r\nSTDiOKyI8uoBdJc0G0l+SLOso4kI8RtaMWI=\r\n=ofCa\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.95-alpha.1-smartgroup_1654761661286_0.16880069536291664"},"_hasShrinkwrap":false},"0.12.95-alpha.2-smartgroup":{"name":"teambition-sdk","version":"0.12.95-alpha.2-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 发布\n注意目前发布要求使用 NPM 二步验证，请参考[文档](https://docs.npmjs.com/configuring-two-factor-authentication#sending-a-one-time-password-from-the-command-line)，在发布命令后面跟随 `--otp=验证码`。\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.95-alpha.2-smartgroup","_nodeVersion":"12.22.7","_npmVersion":"6.14.15","dist":{"integrity":"sha512-wMOVokKGOS9CVz7Uwf3OpWOyuX6XXh0u+SUMjLg+p5yk00h1wzY9nVmtD27LVg2RswjALX7hbEVR37bDxXT5hQ==","shasum":"e34aa75a1dc84a1ce95924e6774ce295c8b282a0","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.95-alpha.2-smartgroup.tgz","fileCount":521,"unpackedSize":1105314,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCpKFOT0Js+M09kZK6s+7OzNDTeplxKLVvTLChP0xVXMwIgcN6DEF9NZS9CrVhwamGq+4FgbbgnYhweU+QVfoYRK98="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiqXwzACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmroTA//Rd4auwIYvoXJe4pzWCwYdDX/7BA5Tig4m/aTArjQOUkQDRal\r\nBTFInsGm2zs3Vgq1x1w63/fSGtK2I+jq8TlEQ2uIxbvAf8XggmSTpSbkJhDN\r\nNleAs2KPvZAt2bej723EtGW5gCBnaJfYzkLpmMDKO1OjD2GpsnCX9j7UzxZS\r\naH5awOLP0mcKU3L7svWwJWbt6IW5m3k11IwdLFRwYLC25sSzGRKJxnLitiX2\r\nkCQ7hdiA7M8JrW9v230Uh1l3bN0ceXxLhCGjQYhH6fqlMDTKaMMz4n3pn0v9\r\nW9LdgwIy3V3HHnq1dycUgbrMNm+MVQ3uCX9fORe/W2iucvXeK4qTwDjOLuex\r\nllO2kxpWbFWtbqsF3CBksy3SdiURme5GI00hdzMEYC4suyJ8GPb0UcNQHIW/\r\nbT1rd4i6BKkb0lL2IugGknApMGdrXhU/PQAq4jO+z31hZn8BxzjPfCR7uyAw\r\nmbgYbzBEC8JcVFZpaAczVQrKQAc8XxWModXWXShkAgVntm/UEUa2Dny3lSbJ\r\neMS/BczLpjo09FJtzAWinxTnonKWfdoXPnRoNkpd89bQ99ToWEFeZAlSnAJC\r\nlObWUX8/kxX596aWUxz/scn67R29DAy6XvZpMBu7nRHhxTswil37QfFr49hG\r\n12o6mE4ra5LV3KzAA3F1kLxptZpVhdxc7sM=\r\n=ENsx\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.95-alpha.2-smartgroup_1655274546833_0.6614669327442515"},"_hasShrinkwrap":false},"0.12.95-alpha.3-smartgroup":{"name":"teambition-sdk","version":"0.12.95-alpha.3-smartgroup","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 发布\n注意目前发布要求使用 NPM 二步验证，请参考[文档](https://docs.npmjs.com/configuring-two-factor-authentication#sending-a-one-time-password-from-the-command-line)，在发布命令后面跟随 `--otp=验证码`。\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.95-alpha.3-smartgroup","_nodeVersion":"12.22.7","_npmVersion":"6.14.15","dist":{"integrity":"sha512-eDze/JiW/8Dqw+gAo+FC6vQ8DZEg1Z78vBCdEFeZewKcrXCKjbVOHL1lWWs82Au1V1Ily6UZH4qFVTs1/FkYHw==","shasum":"4cf58bb7f9495cfa48ff02f285a537d47c53a3ce","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.95-alpha.3-smartgroup.tgz","fileCount":521,"unpackedSize":1105551,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF4+DxWGbv/912F51uI7YGkANzjTRQdWAAhJKaHqAUE/AiEAyQShbne/qxmwbawmhna+kQWKjc3UBX+aUmG84Xlt6D0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiqpNqACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpxuQ/+LkolWBRojAlI9HB8cpd8mq+IG1wjsEY4Firduqsin7b81m9Z\r\noFuTyJC13d1fnmqPAa/CnKOLH88SJeYYnqVRSvUiQWQXxPucvcS2MX9vAD1R\r\ni14igOEVkE5jUAW08jNZEcwhXByH202j13TyNf9besi68K9/xirDTpB27WDV\r\nYv1IQrYXyfOD1d+SWwHnPiVd7/9iPx8kgfFKHTMqnJlLmpXKP6KAz9mevOIq\r\noSv4o2BWfpD4I2njGftUl7TxyMw/ljqNy4VUvZYIYzt17d6F5jzqhRg6yQ0C\r\nHqFq/ci4jBTXEqOngU42F81JSUWhVQ/DgEtK/pgl8XaKVFtBJEFM7Z9b9Wzd\r\nKYE9iAr2WJ4YC6bw5kNPpmwSI3NjFhV9fROmOG+v6PaZPqZp84/329Bnsdjm\r\npfNTSkHl/o00jjxvMtOuAvTViDVpUtCKR4zg1vISzR7tAHRJyoRws+FgqAdr\r\nARXEnzPAHMD0uaxmL7FzhcFeqLKXbD8/NMNYASoDodJ3bsxgFQmPOAZO1E6I\r\nf9ju21BEBKXordLVTzNHqnUKxY4Da8W+nrA40wrgaBCfKE+qgtkG+2242r0r\r\nDCVJhyBIK6IH6tPvntgc8/T53ZAX9yDDDH1b+vELyvEN3eHSImcesmJ1xRmD\r\nWOVVjLzJ9jyg6cQNyLzGPnMIUbQT71ORYuU=\r\n=YTax\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.95-alpha.3-smartgroup_1655346026555_0.2038282672769134"},"_hasShrinkwrap":false},"0.12.95-alpha.4-sfcv2":{"name":"teambition-sdk","version":"0.12.95-alpha.4-sfcv2","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 发布\n注意目前发布要求使用 NPM 二步验证，请参考[文档](https://docs.npmjs.com/configuring-two-factor-authentication#sending-a-one-time-password-from-the-command-line)，在发布命令后面跟随 `--otp=验证码`。\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.95-alpha.4-sfcv2","_nodeVersion":"12.22.7","_npmVersion":"6.14.15","dist":{"integrity":"sha512-8oG/2PfRCI14Pnx9E/sdmB+5a5g3Slm3lbdgQhBiJNpYJL+O7S6HroAHLIO8PiSCygXWeGM1oTBqKkAJRZSEFg==","shasum":"be2f18aa85a8df25c25b27490705b727faeee352","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.95-alpha.4-sfcv2.tgz","fileCount":521,"unpackedSize":1104904,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC21jiVVvJuKhgnDNWkph84/fSWh9GsNz0qXm//+PNW1AiEA7MdKhwGnnJOIyUqhoyV92KahI8SzNL2HGGEbPiYa9Qo="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJisX0CACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpnQg//ROCK6wkEea/EX1WIxYx6jBsKeLBmK6igi1e1CTA6DSYzinIy\r\nwF+WcMicg4Ij1mLkJBlxLDqyuUUrUnl5UEWiXAHlpuzfmq6esA+dCuniTEUa\r\nOwQrMkEAZvlb5cqaPxSC3WlLg3Mo4Nx84uhSv9DO41gvRBDlsi9RjRLMzApw\r\nGInUAFOE/xUh72OkEljZ2F9RCuZEiIfMVbb6s2UOn2u7yZfo5bN0yLTgjU1b\r\n4qEBPQwicjCFhi/l83+gmyTmAl2uKkHuQYsT6JKhS2VXhz5JHOiLRvyTMsj5\r\n5diySsxWA8ZWmfyGZLR9kzDYF6ei1bEs+0jWl41+ZL0VLLmHyAE1n2tz/j5a\r\n9mlbm7q8S4ZuOgveaBFeZfbnxVfuFBTfyuj1lQPtlliKy0mi+7Z+BfQuyxyr\r\nAEdEDINFomnOmOiodPA++j4j1V7p7XPyfbea/ZHV8Iu7GfAkk2kkt+4lv3Tv\r\nA+789s+jHgdYwcWiYOz9kjU8/mo55JW+qnqkVXgk6LJ/LjopA5JveUClQmKA\r\nSy+UBOPnHGTwM06ZQKzt6d5La1O6S4Gruk0ban74bX31/boRXlzUWe3axahV\r\nAA51tfPShZzHfdoyDW7gf5epH62pGWMm2kBmp1Or1qbU5xTfzLZtk/gf816N\r\n7WWnOalBNka+Nwuu555LhExJtDp1JRzoDG4=\r\n=ZHUJ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.95-alpha.4-sfcv2_1655799042122_0.8523267012117353"},"_hasShrinkwrap":false},"0.12.95-alpha.5-tasklist":{"name":"teambition-sdk","version":"0.12.95-alpha.5-tasklist","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 发布\n注意目前发布要求使用 NPM 二步验证，请参考[文档](https://docs.npmjs.com/configuring-two-factor-authentication#sending-a-one-time-password-from-the-command-line)，在发布命令后面跟随 `--otp=验证码`。\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.95-alpha.5-tasklist","_nodeVersion":"12.22.7","_npmVersion":"6.14.15","dist":{"integrity":"sha512-cTcasLVG7RAsuZhMh/0wZQMy/rr9vE93Z7X4uAyaN8UZ25RUqhPbzfxVw8Z9PJsCAWY/f4Dfe6gxdjVteH0zVA==","shasum":"7dcae48d8a374e055de652bf37fef707674fdd7a","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.95-alpha.5-tasklist.tgz","fileCount":521,"unpackedSize":1105746,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDg2sgytomM3nrfIrp+IOSVjSGxqqEzzbc0o1B4X6JZUwIhALM02b438PniPmDAlzpNf9QcGADF6nGJG35NsBR1nBFn"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJitCMEACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrZUw//cI2q/opW+RKdq/YDnnaH5zvuAtBSQgkv1qaX/vDjcVVtvfRB\r\nsfmWarwO6GWaoBtj4GPVza1Ngn6RlZBEHaTMim+2fiPhxhNmVZBpLhgd4Sgw\r\n1sWwO1SsE76ENvKoocLQeCT4jFDNiLsUxQmVrV7IUT0d1vwhrQgP+oMOb1gJ\r\nfEaz6oqOcjrJtl5CT0Pbu+j87W9o2JOrgUeA/cRPaQvLwHBEOQytiO+rQVwI\r\n0wpRnzuXiP+Kuagjct8/s+81SfTw2RxwRLFtGFrg+iHFPEbbIcvlV27yJB7k\r\npV4hx6x7uDyVP8imcLD/+uYEA91Zs1Ms5Zc6U2Bxbyi7qt/LSM+CWDrnLCyT\r\nPaJbrJxU2HK5QplvEQnAJBle8why/qjCuTb0jVupFLO65VwkTkhsAX+iaPH5\r\nU29HU7AGrP75/GsewgusOiBuB+AvP0J8cIbstgayYh5XwBYLGsy/unNI6m/5\r\nM7CfgpIQqUD3w2QpgTeujw74mzz76r29jKcyixGEPBguFf9TamUEyQOMmz65\r\nMIx6/1KcNNkNhghIRnN0u3aHZ/A5h2uOOtWnBiR+29OZE4jg06b+ETy9Jsj7\r\nOQvFbCNWP4LDDHD1VmsrX4sPEUrSD5bowl5ih+Xf51MjAu1LOPG3D83vYdB+\r\nmZhqonvw5Feyi6MXAvVYBXnkYmwo8OaOGok=\r\n=csDY\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.95-alpha.5-tasklist_1655972611747_0.4903376034735252"},"_hasShrinkwrap":false},"0.12.94":{"name":"teambition-sdk","version":"0.12.94","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.94","_nodeVersion":"12.22.7","_npmVersion":"6.14.15","dist":{"integrity":"sha512-HH3rj1x7fMUy+uzgMm4KlR3cEDT0J7Ix+4m7E6Tc8O90brTAEkQG95Uk2N/Kdz8pwfsm6Yxsbl54PBQQ+lwsbQ==","shasum":"d194f0a88de85e7b5a7d3aab1e99cfe521093de1","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.94.tgz","fileCount":521,"unpackedSize":1105539,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA5b0y+L5K5b5p2eImJjtH1/bkH4RnPzn2td+cNEx1onAiAoaVObkfsZDRLAgTVTYxDlXiZlRGPJPyzHZ3xlgzHs+w=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiumQyACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoixA//RFuNNth6N5kJgo3Dfa7KPQfkq1dfCoBuxSH2DVmfE4TPUzLQ\r\nA2a4+KsJ/H6ogwDGFM5vSRO2ffoDln9BbuJjJQDTA5KKcf/pfrmAI15ex7at\r\nzrRroc0cuNujkpqspa+cpmIXGyY2dKP35knzyv1yhNm6/WbxXJ+PpMm9L4Xs\r\n6tNGubVY+vnXF9LX4GTsFV4o1bAeFtVg+NtWzGyZnj2cakcrsDYbJwQXW9zt\r\nGcEJWzrTYktCMyK4GjrT4GgzMyTU9WGNYHTy3XBKftS2v0tWuuXoBGy0L1y8\r\nKBEseYpMja/nQIBU1MBnW/UTB9CBdzHOj+1i98ANSCZZfuwkSXPqrfhj/FRc\r\neABaqzqZl0pd4lK9GAj9OuMNxFMw1aROhSgcg9uh2k4Wdfe5KuKpe9yO8hGo\r\n0g0lx7/ldSJxQOJoQrWzdwFSsAQF77dzP3aVJFjAq1ztj9Mh0rvc/96wcdgh\r\niapzqtbRMH//WJHCaAcdwBBvu3D7fgf6kctW2KKJhG4crB//6eAtjG0EI5CB\r\n++ZTjmKudcLUeeEiD3m0GuzhJnWst2Gd/d4cSvAwrh5jBBH/1/MzIQfFrjda\r\n3G4gx+DAlMSHKDJz23bqhKYdMC1Lx/C7zIgui/wkgmtGoUaGuhE88VgSyilu\r\n3ZljJVfwYCGDwNBB2ASBPTVQCgwDo0Z6nbQ=\r\n=FeQr\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.94_1656382514305_0.5364395910968662"},"_hasShrinkwrap":false},"0.12.95":{"name":"teambition-sdk","version":"0.12.95","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"_id":"teambition-sdk@0.12.95","_nodeVersion":"12.22.7","_npmVersion":"6.14.15","dist":{"integrity":"sha512-c6iT1rmZQEfqhu9jNi4bE/LJYBFzb5cvkhszXOMC3V0T+MXy+aZZJwNsIN/5snmQ6Ln+Zst7v0vqhMCkH27hRA==","shasum":"b0e2625b5b06282d279310b95fbe733462a62009","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.95.tgz","fileCount":521,"unpackedSize":1105736,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCz85HMkl0PXxo4s8e/VkOZpC1dZqq8fNaBF7FEC8oS4wIgQr8CdXPnCDsY9+wRMhDYaaHknjcsi8X+hAtHFHQ5m5A="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJium3EACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq8+BAAnQnTGegVryGZTF/v/b7w7EPvRwweOq3DPnfJNO0nFJd9vFBm\r\ntlryGpG7jUOEe8pz4fOaSHzgrGQjNJKcVYawZiV52KqIrWxw9G4Xbv2b3wNR\r\n5ot3lbERYlge2CFpIJiibjgsLXQ7+Lmjo5Y3JObvvsY95ZGX+PDfX5D+HT1Z\r\nklWEWCWc1SibfKRdWGctE0sPWML2IdoSXUzRHiQXjS/j4/dAS/JA0xuJGK2y\r\nn7suSj0Coym+bv9IwX7F/JDtXxKKQM4+st4YLBmG0BDej74trZiPMn7yVStV\r\nGkW6M6xSR4ORMjkTwgc832zNZW3mnBvbTJldLiKi1HJFTksv2Wrf8iTYIwBa\r\njsRzju8p4GWp+v+/WuBEIjkbMTztISYlcQOgDmypM26dPk/sec6e5/g1Wi2A\r\nmldleMpYgL4llKJIwW762sIW5lizxSCx+lmMVN2nZPKoeTB08BaT50sefxEg\r\nSYQoP2VbVR1xRTLy5xp6Fv5zhjj7ODS1uX0ddmedRYV2jnPzwHhQT17xBL51\r\nf+xIk6ye5XrsFsJszf7VHFdIERtVrKiFPQnFMLF1UxeqquGxYd8jBCiTkV65\r\nh4jorY6ZVJ14+mEPTq5b1tJHrWPQ3ndC0fdVzTn40rqb3HCBkCD4TqjC9mNT\r\nIO8cj04f4kOmefV7EbfpX62wvT+rOc337eI=\r\n=NwXb\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.95_1656384964632_0.8310882610860741"},"_hasShrinkwrap":false},"0.12.95-alpha.1":{"name":"teambition-sdk","version":"0.12.95-alpha.1","description":"Front-End SDK for Teambition","main":"./index.js","typings":"./index.d.ts","scripts":{"build_all":"rm -rf dist && mkdir dist && mkdir dist/bundle && npm run build_es6 && npm run build_cjs && npm run build_bundle && npm run build_mock && npm run build_mock_cjs && npm run build_test && npm run build_socket","build_bundle":"rm -rf dist/bundle/tbsdk.umd.js && ts-node --type-check ./tools/tasks/bundle.sdk.ts","build_cjs":"rm -rf dist/cjs &&      tsc src/index.ts    -m commonjs --outDir dist/cjs      --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_es6":"rm -rf dist/es6 &&      tsc src/index.ts    -m es2015   --outDir dist/es6      --sourcemap --inlineSources --target ES2015 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --importHelpers --noEmitHelpers --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_mock":"rm -rf dist/mock-es6 && tsc mock/index.ts -m es2015  --outDir dist/mock-es6   --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.mock.ts","build_mock_cjs":"rm -rf dist/mock-cjs && tsc mock/index.ts -m commonjs --outDir dist/mock-cjs --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --strict --noUnusedLocals --noUnusedParameters --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","build_socket":"rm -rf dist/bundle/tbsdk.socket.js && tsc ./src/SocketApp.ts ./src/teambition.ts -m commonjs --outDir dist/socket --sourcemap --inlineSources --target ES5 -d --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --moduleResolution node --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy && ts-node --type-check ./tools/tasks/bundle.socket.ts","build_test":"rm -rf spec-js && tsc test/app.ts -m commonjs --sourcemap --inlineSources --outDir spec-js --target ES2015 --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node","check_circular_dependencies":"npm run build_cjs && madge ./dist/cjs --circular","copy_files":"cp README.md package.json ./dist/cjs/","cover":"export TZ=\"America/Chicago\"; npm run build_test && rm -rf ./coverage && nyc --reporter=html --reporter=lcov --exclude=node_modules --exclude=spec-js/test --exclude=spec-js/mock --exclude=spec-js/src/sockets/SocketClient.js tman --mocha spec-js/test/app.js","lint":"tslint ./src/**/*.ts ./mock/**/*.ts ./test/*.ts ./test/apis/**/*.ts ./test/mock/**/*.ts ./test/utils/**/*.ts","publish_sdk":"npm run build_all && npm run copy_files && ts-node tools/tasks/npm-publish.ts ./dist/cjs","publish_all":"npm run publish_sdk && ts-node --type-check ./tools/tasks/publish.ts && cp -r ./dist/mock-cjs/** ./.tmp/mock && cp -r ./dist/socket/** ./.tmp/socket && npm publish .tmp/mock/ && npm publish .tmp/socket/","test":"npm run lint && npm run check_circular_dependencies && npm run cover","preversion":"ts-node tools/tasks/version.ts preversion","watch":"export TZ=\"America/Chicago\"; npm run watch_test & ts-node ./tools/tasks/test.ts $!","watch_cjs":"tsc src/index.ts  -m commonjs --outDir dist/cjs --sourcemap --inlineSources --target ES5    -d --diagnostics --pretty --experimentalDecorators --strict --noUnusedLocals --noUnusedParameters --suppressImplicitAnyIndexErrors --moduleResolution node --skipLibCheck -w --lib es5,es2015.iterable,es2015.collection,es2015.promise,es2015.core,dom,es2015.proxy","watch_test":"tsc test/app.ts  -m commonjs --outDir spec-js  --sourcemap --inlineSources --target ES2015    --diagnostics --pretty --experimentalDecorators --suppressImplicitAnyIndexErrors --types \"node,chai,sinon,sinon-chai\" --moduleResolution node --skipLibCheck -w"},"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"keywords":["teambition","sdk","teambition-sdk"],"author":{"name":"lynweklm@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"homepage":"https://github.com/teambition/teambition-sdk#readme","peerDependencies":{"reactivedb":"~0.10.2","rrule":"2.2.0","rxjs":"^5.2.0","snapper-consumer":"^1.3.6","tslib":"^1.9.0"},"devDependencies":{"@types/chai":"^4.0.4","@types/lodash":"^4.14.74","@types/lovefield":"^2.1.1","@types/node":"^9.3.0","@types/sinon":"^4.0.0","@types/sinon-chai":"^2.7.29","@types/uuid":"^3.4.3","atob":"^2.1.2","chai":"^4.1.2","coveralls":"^3.0.0","engine.io-client":"^3.1.0","fetch-mock":"^5.12.2","google-closure-compiler-js":"^20180506.0.0","isomorphic-fetch":"^2.2.1","jsonrpc-lite":"^1.3.0","madge":"^3.3.0","mock-require":"^3.0.3","moment":"^2.18.1","node-watch":"^0.5.8","nyc":"^11.2.1","reactivedb":"~0.10.2","rollup":"^0.60.5","rollup-plugin-alias":"^1.3.1","rollup-plugin-commonjs":"^8.4.1","rollup-plugin-node-resolve":"^3.0.0","rrule":"2.2.0","rxjs":"^5.4.3","rxjs-marbles":"^2.4.1","semver":"^5.5.0","sinon":"^4.0.0","sinon-chai":"^2.14.0","snapper-consumer":"^1.3.6","teambition-sdk-mock":"^0.6.8","tman":"^1.7.2","ts-node":"^7.0.1","tslib":"^1.9.3","tslint":"^5.11.0","tslint-eslint-rules":"^5.4.0","typescript":"^3.1.6","uuid":"^3.3.2"},"readme":"[![CircleCI](https://circleci.com/gh/teambition/teambition-sdk/tree/release.svg?style=svg)](https://circleci.com/gh/teambition/teambition-sdk/tree/release)\n[![Coverage Status](https://coveralls.io/repos/github/teambition/teambition-sdk/badge.svg?branch=release)](https://coveralls.io/github/teambition/teambition-sdk?branch=release)\n[![Dependency Status](https://david-dm.org/teambition/teambition-sdk.svg)](https://david-dm.org/teambition/teambition-sdk)\n[![devDependency Status](https://david-dm.org/teambition/teambition-sdk/dev-status.svg)](https://david-dm.org/teambition/teambition-sdk?type=dev)\n\n# isomorphic-sdk for Teambition APIs\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/teambition/teambition-sdk.svg)](https://greenkeeper.io/)\n\n## 安装\n\n```bash\nnpm install teambition-sdk --save-dev\n```\n如果要求在不支持 Fetch API 的浏览器运行，请安装 polyfill 如 [whatwg-fetch](https://github.com/github/fetch)。\n\n## 开发\n\n目前主分支是 `release`，而 `master` 只应用于部分处于维护状态的老项目。常用命令如：\n\n```bash\nyarn               # 安装依赖\nnpm run build_test # 构建测试\nnpm test           # 跑一遍完整测试\nnpm watch          # 在开发时，以监听模式跑测试，每次代码修改都会重跑测试，帮助及时发现问题\n```\n\n## 发布\n注意目前发布要求使用 NPM 二步验证，请参考[文档](https://docs.npmjs.com/configuring-two-factor-authentication#sending-a-one-time-password-from-the-command-line)，在发布命令后面跟随 `--otp=验证码`。\n```bash\n# only publish sdk\nnpm run preversion   # 查询 npm 官方库，获取当前发布的最新正式版本和最高的预发版本号，避免打版本时出错\nnpm version v0.12.68 # 打正式版本 0.12.68（包括创建相应标签）\nnpm version v0.12.69-alpha.0-readme # 打预发版本 0.12.69-alpha.0-readme（包括创建相应标签）\nnpm run publish_sdk  # 在本地 build 当前代码并发布到 npm 官方库\n# 完成发布后，推荐将相应标签（tag）推到远端，如 `git push origin v0.12.69-alpha.0-readme`\n\n# publish sdk, mock and socket\nnpm version xxx\nnpm run publish_all\n```\n\n## 设计理念\n\nSDK 主要解决的是数据同步的问题。通俗点讲，就是在前端使用数据模型模拟出数据库的增删改查等操作。\n\n为什么会有这种需求? 以 `https://api.teambition.com/tasks/:_id` 为例， Teambition 的 API 会返回下面格式的数据:\n\n```json\n{\n  \"_id\": \"001\",\n  \"name\": \"task\",\n  \"executor\": {\n    \"_id\": \"002\",\n    \"name\": \"executor 1\",\n    \"avatarUrl\": \"https://xxx\"\n  },\n  \"subtasks\": [\n    {\n      \"_id\": \"003\",\n      \"name\": \"subtask\",\n      \"executor\": {\n        \"_id\": \"004\",\n        \"name\": \"executor 2\",\n        \"avatarUrl\": \"https://xxx\"\n      }\n    }\n  ]\n}\n```\n\n而倘若这个任务中包含的子对象，比如 `executor` 字段对应的数据通过其它 API 进行了变更:\n\n```ts\n/**\n * @url https://api.teambition.com/subtasks/:_id\n * @method put\n * @body {name: 'executor test'}\n */\nSubtasksAPI.update('002', {\n  name: 'subtask update'\n})\n  .subscribe()\n```\n\n在前端，需要自行处理与此 subtask 相关的所有变更情况。例如:\n\n1. 包含这个子任务的列表中的这个子任务名字的变更。\n2. 包含这个子任务的任务的详情页中，该子任务名字的变更。\n\n然而在现有的 Teambition 数据模型中，需要在每一个 `Model` 或者 `Collection` 或者 `View` 中手动监听与自己相关联的数据，例如:\n\n```js\n// 匹配第一种情况\nclass MyTasksView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(warehouse, ':change:task', model => {\n      // handler\n    })\n    this.listenTo(warehouse, ':change:subtask', model => {\n      // handler\n    })\n  }\n}\n```\n\n```js\n// 匹配第二种情况\n\nclass SubtaskCollection extends Backbone.Collection {\n  ...\n\n  constructor() {\n    this.on('add destroy remove change:isDone', () =>\n      Socket.trigger(`:change:task/${this._boundToObjectId}`, {\n        subtaskCount: {\n          total: this.length\n          done: this.getDoneSubTaskCount()\n        }\n      })\n    )\n  }\n  getDoneSubTaskCount() {\n    this.where({isDone: true}).length\n  }\n}\n\nclass TaskView extends Backbone.View {\n  ...\n  listen() {\n    this.listenTo(this.taskModel, 'change', this.render)\n  }\n}\n```\n\n而在当前的设计中，所有的这种变更情况都在数据层处理，视图/业务 层只需要订阅一个数据源，这个数据源随后的所有变更都会通知到订阅者。\n比如获取一个任务:\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'teambition-sdk/apis/task'\nimport { SDK } from 'teambition-sdk/SDK'\nimport { Component, Input } from '@angular/core'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = this.SDK.getTask(this.taskId)\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n}\n```\n\n\n如果更加纯粹的使用 RxJS，甚至可以组合多种数据和业务:\n\n\n```ts\nimport 'rxjs/add/operator/distinctUntilKeyChanged'\nimport 'rxjs/add/operator/distinctUntilChanged'\nimport 'teambition-sdk/apis/permission'\nimport 'teambition-sdk/apis/task'\nimport 'teambition-sdk/apis/project'\nimport { SDK } from 'teambition-sdk'\nimport { Component, Input } from '@angular/core'\nimport * as moment from 'moment'\nimport { errorHandler } from '../errorHandler'\n\n@Component({\n  selector: 'task-detail',\n  template: `\n    <div [ngClass]=\"{'active': permission$.canEdit | async}\"></div>\n    <div> {{ task$?.name | async }} </div>\n    <div> {{ subtaskCount$ | async }} </div>\n    <div> {{ dueDate$ | async }} </div>\n  `\n})\nexport default class TaskView {\n\n  @Input('taskId') taskId: string\n\n  private task$ = SDK.getTask(this.taskId)\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private subtaskCount$ = this.task$\n    .distinctUntilKeyChanged('subtasks')\n    .map(task => ({\n      total: task.subtasks.length,\n      done: task.subtasks.filter(x => x.isDone).length\n    }))\n\n  private dueDate$ = this.task$\n    .map(task => moment(task.dueDate).format())\n\n  private project$ = this.task$\n    .distinctUntilKeyChanged('_projectId')\n    .switchMap(task => SDK.getProject(task._projectId))\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n\n  private permission$ = this.task$\n    .distinctUntilChanged((before, after) => {\n      return before._executorId === after._executorId &&\n        before._projectId === after._projectId\n    })\n    .switchMap(task => {\n      return this.project$\n        .distinctUntilKeyChanged('_defaultRoleId')\n        .switchMap(project => {\n          return SDK.getPermission(task, project)\n        })\n    })\n    .catch(err => errorHandler(err))\n    .publishReplay(1)\n    .refCount()\n```\n\n在这种场景下，关于 task 的任何变更 (tasklist 变更，executor 变更，stage 变更等等，权限变化) 都能让相关的数据自动更新，从而简化 View 层的逻辑。\n","readmeFilename":"README.md","_id":"teambition-sdk@0.12.95-alpha.1","_nodeVersion":"12.22.7","_npmVersion":"6.14.15","dist":{"integrity":"sha512-WRKgarWycyLsdQ7/CeztljGKX/JRTx5R1KgNcb0QQ6TKycuXEIB15MK11kU/dIp19Af0U+t6xq/IwvqKmqPgyQ==","shasum":"5aa5273568a40856270da8c727fb5732b1284e05","tarball":"https://registry.npmjs.org/teambition-sdk/-/teambition-sdk-0.12.95-alpha.1.tgz","fileCount":521,"unpackedSize":1105575,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDIcgV6Bhaw8+qvQu6gwFFycdmMyIF9c88gdHaoEGXFyQIhAKzLodt6FsUONq1hvYuJtlZx728B3FiEDY+Kzm6ZlHo1"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJix9yIACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoMGw/+Ll99d0eLn+A1uRmx0UgkHHEc4o2uHUTYWO0QhpyYs5r50/Xt\r\nxObNUCRT3/qAiSJQM4GUXm07MSaa7gEzvEb8BpHghmDMdZU2B6W2DXCAOPp5\r\n9GDFQms/QxWB1DVfi3RXYqKk55+3ULCVA5E/4L1U0hWQein6LUaHiJj1C7qp\r\nCj16MxfG/Uq54UJ76vdMjoadDmX38dQ0efD46UkKzJBthR3Ell4TNLbJepTJ\r\nyODyXUzaXLy9uOSLeo1wBj11tyhtPKcvof1f7hdJ68aAGaQsXQJKlhP4DUn8\r\nJyCdxErj/j/9eBWl02Lka8+gTmUxl/JUTEAqrRXEuyub1vQyqVnZuNSgeYvV\r\nYyAo414UsB5p7tH01XRP8SaqIHeV2bRcYZyOSzN72hPimfRVTxiidINRWJIH\r\n3MV7gOq9jIPlZt9AsSq3zK/nSIGjOymqZCZ/hOtBP+A7Ildb5wPj+qwVI3C/\r\nWaa4j+d29vZQFC58Clxw25H2kxP1ytsaevn5ta+cZ8VQykCibHQ8zjTlsyy9\r\nJ1Du8UsvKOh4adKRGMGV1iOn+H2DUxrqBxXPDYd0uQfceZyloSnEP+R3XT/G\r\nu/zI+ITDWG1Kt/73y0BeGW41l+wAjDxKfXkDJJ33T0dhsX/RWeVzAkCpwFEU\r\nEh7f+FHez360AFtVPX9yPY/xo3rRFOT0fkU=\r\n=aeaX\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"2ehao","email":"zzh209519@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/teambition-sdk_0.12.95-alpha.1_1657265287920_0.5975248875975698"},"_hasShrinkwrap":false}},"readme":"","maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"},{"name":"saviio","email":"sirius0x9@gmail.com"},{"name":"chuan6","email":"chuan6.dev@gmail.com"},{"name":"jinchang","email":"chang@teambition.com"},{"name":"nekolabs","email":"ratsunny@gmail.com"},{"name":"2ehao","email":"zzh209519@alibaba-inc.com"}],"time":{"modified":"2022-07-08T07:28:08.301Z","created":"2016-03-05T05:18:30.881Z","0.0.1":"2016-03-05T05:18:30.881Z","0.0.2":"2016-03-05T05:22:02.520Z","0.0.3":"2016-03-05T05:24:20.449Z","0.1.0":"2016-03-16T09:32:30.897Z","0.2.0":"2016-05-31T05:52:29.877Z","0.2.1":"2016-06-03T07:01:20.659Z","0.2.2":"2016-06-30T09:06:46.683Z","0.2.3":"2016-07-04T10:22:08.173Z","0.2.4":"2016-07-06T08:16:50.357Z","0.2.5":"2016-07-10T10:44:06.462Z","0.2.6":"2016-07-11T16:37:36.111Z","0.2.7":"2016-07-11T16:42:10.400Z","0.2.8":"2016-07-13T03:09:45.410Z","0.2.9":"2016-07-14T07:08:33.025Z","0.2.10":"2016-07-15T10:56:43.640Z","0.2.11":"2016-07-17T03:15:02.058Z","0.2.12":"2016-07-17T03:18:32.194Z","0.2.13":"2016-07-19T09:26:42.683Z","0.2.14":"2016-07-20T11:02:58.608Z","0.2.15":"2016-07-22T09:49:35.258Z","0.2.16":"2016-07-26T02:44:33.861Z","0.2.17":"2016-07-26T03:09:58.174Z","0.2.18":"2016-07-27T13:53:50.996Z","0.2.19":"2016-07-27T14:11:05.172Z","0.2.20":"2016-07-27T15:58:09.414Z","0.2.21":"2016-07-29T08:42:35.656Z","0.3.0":"2016-08-04T13:09:06.442Z","0.3.1":"2016-08-09T07:04:15.980Z","0.3.2":"2016-08-09T11:21:11.598Z","0.3.3":"2016-08-16T12:20:59.575Z","0.3.4":"2016-08-16T12:23:14.369Z","0.3.5":"2016-08-17T07:36:32.946Z","0.3.6":"2016-08-19T11:03:52.896Z","0.3.7":"2016-08-24T04:40:47.810Z","0.4.0-alpha.1":"2016-08-29T10:11:18.976Z","0.4.0-alpha.2":"2016-08-30T05:33:13.301Z","0.4.0-alpha.3":"2016-09-01T03:46:08.643Z","0.4.0-alpha.4":"2016-09-01T11:25:16.531Z","0.4.0-alpha.5":"2016-09-12T09:57:55.360Z","0.4.0-alpha.6":"2016-09-14T10:56:46.908Z","0.4.0-rc.0":"2016-09-23T11:13:05.463Z","0.4.0-rc.1":"2016-09-28T10:20:46.270Z","0.4.0-rc.2":"2016-09-29T05:49:36.949Z","0.4.0":"2016-09-29T10:06:07.874Z","0.4.1":"2016-10-10T10:01:13.731Z","0.5.0":"2016-10-11T06:39:08.171Z","0.5.1":"2016-10-11T11:53:33.926Z","0.5.0-beta.1":"2016-10-17T01:38:58.387Z","0.5.0-beta.2":"2016-10-17T08:00:26.629Z","0.5.0-beta.3":"2016-10-17T08:13:08.394Z","0.5.2":"2016-10-18T10:12:10.852Z","0.5.0-beta.4":"2016-10-19T08:22:25.166Z","0.5.0-beta.5":"2016-10-24T03:48:54.672Z","0.6.0-rc.1":"2016-10-27T02:36:13.117Z","0.6.0-rc.2":"2016-10-27T03:59:07.428Z","0.6.0":"2016-11-01T02:06:01.316Z","0.5.3":"2016-11-01T02:27:52.592Z","0.6.1":"2016-11-01T02:32:12.611Z","0.6.2":"2016-11-07T08:52:15.355Z","0.6.3":"2016-11-23T06:54:57.578Z","0.6.4":"2016-12-05T05:53:45.463Z","0.6.5":"2016-12-21T08:43:16.379Z","0.6.6":"2016-12-26T05:31:48.091Z","0.7.0-alpha.1":"2017-01-17T10:33:48.915Z","0.7.0-alpha.2":"2017-01-17T13:57:46.857Z","0.7.0-alpha.3":"2017-01-18T03:13:07.144Z","0.6.7":"2017-01-18T04:00:53.288Z","0.6.8":"2017-01-24T06:39:41.758Z","0.7.0-alpha.4":"2017-02-14T08:27:55.076Z","0.7.0-alpha.5":"2017-02-14T08:34:02.380Z","0.7.0-alpha.6":"2017-02-14T08:38:15.916Z","0.7.0-alpha.7":"2017-02-14T08:40:19.755Z","0.7.0-alpha.8":"2017-02-14T08:46:59.881Z","0.7.0-alpha.9":"2017-02-16T09:07:18.399Z","0.7.0-alpha.10":"2017-02-20T05:22:53.403Z","0.7.0-alpha.11":"2017-02-20T05:27:19.766Z","0.7.0-alpha.12":"2017-02-20T05:30:34.706Z","0.7.0-alpha.13":"2017-02-20T05:32:19.395Z","0.7.0-alpha.14":"2017-02-20T05:36:51.685Z","0.7.0-alpha.15":"2017-02-21T09:30:36.007Z","0.7.0-alpha.16":"2017-02-22T03:08:58.648Z","0.7.0-alpha.17":"2017-02-22T05:46:58.796Z","0.7.0-alpha.18":"2017-02-22T07:05:59.629Z","0.7.0-alpha.19":"2017-02-22T07:17:45.824Z","0.7.0-alpha.20":"2017-02-23T02:08:38.500Z","0.7.0-alpha.21":"2017-02-23T07:26:35.310Z","0.7.0-alpha.22":"2017-02-23T08:41:44.699Z","0.7.0-alpha.23":"2017-03-01T07:23:05.855Z","0.7.1":"2017-03-02T04:01:32.873Z","0.7.2":"2017-03-06T09:17:14.024Z","0.7.3":"2017-03-24T09:27:39.938Z","0.7.4":"2017-03-30T04:17:22.123Z","0.7.5":"2017-03-31T06:29:07.387Z","0.7.6":"2017-04-06T07:08:20.057Z","0.7.7":"2017-04-09T03:31:52.421Z","0.7.8":"2017-04-11T06:34:11.908Z","0.8.0":"2017-04-24T08:36:04.955Z","0.8.1-alpha.0":"2017-04-26T07:14:35.851Z","0.8.1":"2017-04-27T05:08:34.618Z","0.8.2-alpha.0":"2017-05-08T02:10:36.641Z","0.8.2-alpha.1":"2017-05-15T09:19:19.036Z","0.8.2-alpha.2":"2017-05-15T09:22:19.583Z","0.8.2-alpha.3":"2017-05-15T09:42:02.967Z","0.8.2-alpha.4":"2017-05-17T06:49:33.893Z","0.8.2-alpha.5":"2017-05-19T06:22:54.020Z","0.8.2":"2017-05-19T06:32:41.341Z","0.8.3":"2017-05-26T08:48:00.159Z","0.8.4-alpha.0":"2017-05-27T10:20:05.917Z","0.8.4":"2017-06-01T03:15:44.848Z","0.6.9":"2017-06-06T11:08:50.534Z","0.8.5":"2017-06-07T05:54:52.487Z","0.8.6":"2017-06-16T09:10:21.866Z","0.8.7":"2017-06-16T09:27:42.406Z","0.8.8":"2017-06-22T08:23:37.041Z","0.8.9":"2017-06-22T14:49:58.528Z","0.8.10":"2017-06-27T09:58:19.010Z","0.6.10":"2017-06-30T03:02:34.097Z","0.8.11-alpha":"2017-07-14T10:23:51.482Z","0.8.11-alpha.1":"2017-07-14T10:33:20.378Z","0.8.11-alpha.2":"2017-07-17T08:17:01.766Z","0.8.11-alpha.3":"2017-07-20T07:54:24.170Z","0.8.11-alpha.4":"2017-07-25T02:43:56.107Z","0.8.11":"2017-07-28T10:11:29.718Z","0.8.12":"2017-08-01T10:02:22.804Z","0.8.13":"2017-08-01T12:15:28.063Z","0.8.14":"2017-08-03T06:00:33.461Z","0.8.15":"2017-08-09T01:38:35.904Z","0.8.15-alpha.1-tapestry":"2017-08-10T07:56:25.191Z","0.8.16":"2017-08-10T09:37:33.898Z","0.8.17":"2017-08-14T09:41:05.995Z","0.8.17-alpha.1":"2017-08-23T01:12:57.476Z","0.8.17-alpha.2":"2017-08-28T06:40:27.755Z","0.8.18":"2017-08-29T02:39:44.073Z","0.8.18-alpha.1-mobile-web":"2017-09-04T11:05:18.465Z","0.8.19-alpha.1-members-fix":"2017-09-04T11:10:41.140Z","0.8.19-alpha.2-members-fix":"2017-09-04T11:25:38.144Z","0.8.19":"2017-09-07T08:07:47.411Z","0.8.20-alpha.1-members-fix":"2017-09-07T08:16:50.575Z","0.8.20-alpha.2":"2017-09-13T15:32:37.978Z","0.8.20-alpha.3-join-user":"2017-09-15T01:29:59.137Z","0.8.20":"2017-09-15T10:08:02.897Z","0.9.0-alpha.1":"2017-09-26T06:16:57.173Z","0.9.0-alpha.2":"2017-09-26T06:23:39.379Z","0.6.11":"2017-09-27T10:46:22.889Z","0.8.21":"2017-09-29T02:34:37.464Z","0.8.22":"2017-10-12T05:49:34.975Z","0.8.23-alpha.1-objectlinkschema":"2017-10-12T09:51:11.996Z","0.8.23-alpha.2-eventschema":"2017-10-13T06:16:16.186Z","0.8.23":"2017-10-20T07:46:22.093Z","0.8.22-patch.1-creatorisrobot":"2017-10-25T09:07:44.911Z","0.8.24":"2017-10-26T04:01:00.952Z","0.8.25-alpha.1-objectlinkshcema":"2017-10-27T08:16:42.231Z","0.8.25":"2017-11-02T09:44:51.875Z","0.8.26-alpha.1-members-fix":"2017-11-07T04:04:46.838Z","0.8.26-alpha.1-sprintschema":"2017-11-17T10:07:12.543Z","0.8.26-alpha.2-sprintschema":"2017-11-17T10:09:45.367Z","0.8.26-alpha.3-smartgroupschema":"2017-11-18T03:38:09.894Z","0.8.26-alpha.4-taskschemasprint":"2017-11-21T09:52:00.391Z","0.8.26-alpha.5-taskschemasprint":"2017-11-21T10:11:55.833Z","0.8.26-alpha.6-customlinkfieldsocket":"2017-11-23T08:56:56.232Z","0.8.26-alpha.7-wschanges":"2017-11-24T12:22:18.672Z","0.9.0-alpha.1-allday":"2017-11-29T11:19:30.420Z","0.9.0-alpha.2-allday":"2017-11-29T13:13:12.781Z","0.8.26-alpha.8-wsremoves":"2017-11-29T14:24:34.160Z","0.8.26-alpha.9-sprintschema":"2017-11-30T04:07:53.776Z","0.8.26-alpha.10-sprintschema":"2017-11-30T04:22:03.932Z","0.8.26-alpha.11-smartgrouptype":"2017-11-30T05:26:51.825Z","0.9.0-alpha.3-allday":"2017-11-30T09:51:53.624Z","0.9.0-alpha.4-allday":"2017-12-01T02:20:08.892Z","0.8.26":"2017-12-01T08:29:52.430Z","0.8.27":"2017-12-05T03:15:12.865Z","0.8.28-alpha.1-tasklikes":"2017-12-06T16:50:25.891Z","0.9.0-alpha.5-allday":"2017-12-07T04:03:38.029Z","0.8.28-alpha.2-teammember":"2017-12-13T03:30:59.082Z","0.8.28-alpha.3-groupschema":"2017-12-21T02:17:29.244Z","0.8.28":"2017-12-21T06:44:33.269Z","0.9.0-alpha.6-alldayrecur":"2017-12-22T05:25:42.913Z","0.9.0-alpha.7-alldayparse":"2017-12-25T08:21:07.418Z","0.9.0-alpha.8-alldayapi":"2017-12-27T08:32:10.310Z","0.8.29":"2017-12-29T04:04:14.189Z","0.9.0-alpha.9-allday":"2017-12-29T09:35:46.970Z","0.9.0-alpha.10-alldayleaveschema":"2018-01-03T07:33:53.421Z","0.8.30":"2018-01-04T05:55:44.624Z","0.9.0-alpha.11-scenariosubtask":"2018-01-04T06:53:53.126Z","0.9.0-alpha.12-nonalldayattrs":"2018-01-04T09:49:39.030Z","0.9.0-alpha.13-datetotime":"2018-01-04T16:19:41.214Z","0.9.0-alpha.14-teamschema":"2018-01-05T08:49:24.784Z","0.9.0-alpha.14-sconfigsubtask":"2018-01-10T11:28:11.935Z","0.9.0":"2018-01-11T11:37:21.568Z","0.9.1-alpha.1-teamschema":"2018-01-16T02:32:54.590Z","1.0.0-alpha.1-wsmidware":"2018-01-23T14:15:34.299Z","0.10.0-alpha.1-wsmidware":"2018-01-24T03:05:53.286Z","0.9.1":"2018-01-26T09:02:14.222Z","0.10.0-alpha.2-wsmsgonly":"2018-01-30T03:00:47.837Z","0.10.0-alpha.3-wsmsgfix":"2018-01-30T03:54:55.081Z","0.10.0-alpha.4-wsintercept":"2018-01-31T10:02:04.561Z","0.10.0-alpha.5-wsrefresh":"2018-02-02T09:22:18.465Z","0.10.0-alpha.6-wsdeamon":"2018-02-05T13:19:26.547Z","0.10.0-alpha.7-wsonrefresh":"2018-02-06T07:45:15.587Z","0.10.0-alpha.8-socket":"2018-02-08T03:51:53.776Z","0.10.0-alpha.9-wsworks":"2018-02-09T08:30:03.016Z","0.9.2":"2018-03-01T02:11:44.265Z","0.11.0-alpha.1-taskflow":"2018-03-02T03:02:34.193Z","0.11.0-alpha.2-taskflow":"2018-03-05T02:38:24.202Z","0.11.0-alpha.3-taskflow":"2018-03-08T08:49:31.942Z","0.11.0-alpha.4-taskflow":"2018-03-12T03:06:03.210Z","0.11.0-alpha.5-taskflow":"2018-03-14T09:24:56.621Z","0.11.0-alpha.6-taskflow":"2018-03-16T04:14:47.530Z","0.11.0-alpha.7-taskflow":"2018-03-19T08:08:53.471Z","0.9.3":"2018-03-19T11:26:22.948Z","0.11.0-alpha.8-taskflow":"2018-03-20T07:31:34.669Z","0.11.0-alpha.9-taskflow":"2018-03-20T08:24:55.314Z","0.9.4":"2018-03-26T09:08:52.018Z","0.11.0":"2018-03-28T09:33:20.435Z","0.9.5-alpha.0-httpheaders":"2018-03-30T10:17:17.532Z","0.9.5-alpha.1-urlencode":"2018-04-11T03:26:30.711Z","0.11.1":"2018-04-11T05:39:38.836Z","0.11.2":"2018-04-12T10:02:31.088Z","0.6.12":"2018-04-13T13:10:51.186Z","0.6.13":"2018-04-18T07:02:14.274Z","0.11.3":"2018-04-19T04:03:09.232Z","0.11.4":"2018-04-20T06:54:42.707Z","0.11.5":"2018-04-20T07:31:02.764Z","0.6.15":"2018-04-23T11:01:52.078Z","0.11.6":"2018-04-24T10:06:15.161Z","0.6.17":"2018-04-25T04:04:16.145Z","0.6.18":"2018-04-26T05:01:33.682Z","0.6.20":"2018-04-26T06:12:52.858Z","0.11.7":"2018-04-26T07:06:38.901Z","0.6.21":"2018-04-27T03:48:40.666Z","0.12.0-alpha.0-wsmidware":"2018-05-03T12:19:29.328Z","0.6.22":"2018-05-08T09:45:30.601Z","0.11.8":"2018-05-09T07:51:41.822Z","0.12.0":"2018-05-11T09:38:45.225Z","0.11.9":"2018-05-25T06:42:59.931Z","0.11.10":"2018-05-25T09:06:13.158Z","0.11.11-alpha.1-cfc":"2018-05-28T11:25:22.655Z","0.11.11-alpha.2-cfl":"2018-06-01T05:35:30.264Z","0.11.11-alpha.3-cfl":"2018-06-06T05:55:25.253Z","0.11.12-alpha.0-dbcard":"2018-06-06T07:58:54.181Z","0.11.11":"2018-06-06T08:14:05.114Z","0.11.12-alpha.1-dbcard":"2018-06-08T12:43:27.158Z","0.12.1":"2018-06-10T08:25:10.072Z","0.12.2":"2018-06-10T08:40:02.562Z","0.12.3":"2018-06-10T08:58:45.975Z","0.11.12-alpha.2-acf":"2018-06-14T05:58:04.844Z","0.12.4-alpha.0-dbcard-wsproxy":"2018-06-15T05:16:06.859Z","0.11.12-alpha.3-acf":"2018-06-20T03:46:06.304Z","0.11.12-alpha.4-agile":"2018-06-21T07:49:31.400Z","0.12.4-alpha.1-idtyping":"2018-06-24T11:44:43.452Z","0.11.12":"2018-06-25T01:40:51.341Z","0.12.4":"2018-06-27T03:29:57.494Z","0.12.5":"2018-06-28T05:39:25.070Z","0.11.13-alpha.0-orgsfc":"2018-06-28T10:45:55.489Z","0.12.6":"2018-06-28T13:39:39.390Z","0.12.7-alpha.0-egenperf":"2018-07-04T10:30:25.297Z","0.12.7":"2018-07-04T12:07:26.966Z","0.12.8-alpha.0-pagination":"2018-07-05T01:25:34.575Z","0.12.8-alpha.1-page":"2018-07-05T02:25:03.492Z","0.12.8":"2018-07-05T06:52:31.800Z","0.12.9-alpha.0-cgrp":"2018-07-06T09:43:07.050Z","0.12.9-alpha.1-page":"2018-07-10T03:37:58.147Z","0.12.9":"2018-07-10T14:48:05.718Z","0.6.25":"2018-07-11T03:54:31.749Z","0.12.10-alpha.0-cgrp":"2018-07-11T10:24:03.375Z","0.12.10-alpha.1-cfworks":"2018-07-16T07:19:02.895Z","0.12.10-alpha.2-pjtmpl":"2018-07-17T06:45:36.817Z","0.12.10-alpha.3-cfwork":"2018-07-17T07:29:20.045Z","0.6.26":"2018-07-18T04:14:34.543Z","0.12.10":"2018-07-18T07:34:44.803Z","0.6.27":"2018-07-20T02:45:04.678Z","0.12.11-alpha.0-tfs":"2018-07-25T08:14:59.280Z","0.12.11-alpha.1-rid":"2018-07-31T03:27:23.011Z","0.12.11-alpha.2-ridall":"2018-07-31T07:36:14.395Z","0.12.11-alpha.3-ridheaders":"2018-08-01T03:14:20.278Z","0.12.11-alpha.4-ridready":"2018-08-01T10:01:49.836Z","0.12.11-alpha.5-rid":"2018-08-01T10:11:40.503Z","0.12.11-alpha.6-psa":"2018-08-06T01:37:28.638Z","0.12.11-alpha.7-rid":"2018-08-06T08:58:44.444Z","0.12.11-alpha.8-rid":"2018-08-06T09:17:54.322Z","0.12.11-alpha.9-multireminder":"2018-08-06T10:54:28.646Z","0.12.11":"2018-08-07T02:49:44.654Z","0.12.12-alpha.0-testplan":"2018-08-07T05:53:30.300Z","0.12.12":"2018-08-08T08:42:49.821Z","0.12.13-alpha.0-pagination":"2018-08-09T03:02:26.538Z","0.12.13":"2018-08-09T07:58:43.882Z","0.12.14-alpha.0-testplan":"2018-08-09T09:12:40.082Z","0.12.14":"2018-08-09T12:17:08.625Z","0.12.15-alpha.0-headerspolyfill":"2018-08-10T02:40:43.189Z","0.12.15-alpha.1-opfetchpolyfill":"2018-08-13T01:49:38.452Z","0.12.15":"2018-08-13T08:33:38.066Z","0.12.16-alpha.0-testplan":"2018-08-15T06:42:17.791Z","0.12.16-alpha.1-testplan":"2018-08-15T07:12:56.901Z","0.12.16":"2018-08-15T10:24:18.750Z","0.12.17-alpha.0-tasktypeicon":"2018-08-16T01:56:46.102Z","0.12.17":"2018-08-16T02:10:45.525Z","0.12.18-alpha.0-taskdep":"2018-08-17T09:38:54.568Z","0.12.16-alpha.2-testplan":"2018-08-27T05:42:52.727Z","0.12.18":"2018-08-27T05:49:27.055Z","0.12.18-alpha.1-testplan":"2018-08-27T10:56:52.377Z","0.12.18-alpha.2-testplan":"2018-08-27T11:02:53.357Z","0.12.19-alpha.0-orgowner":"2018-08-31T05:46:02.285Z","0.12.19":"2018-08-31T06:34:05.324Z","0.12.20":"2018-09-04T04:20:49.333Z","0.12.20-alpha.0-testplan":"2018-09-06T08:54:23.562Z","0.12.21-alpha.0-testApp.0":"2018-09-07T02:32:40.784Z","0.12.21-alpha.1-testApp.0":"2018-09-11T09:31:00.920Z","0.12.21-alpha.2-testApp.1":"2018-09-12T06:21:09.795Z","0.12.21":"2018-09-13T06:18:04.668Z","0.12.22-alpha.0-taskdep":"2018-09-13T06:39:58.316Z","0.12.21-alpha.3-testApp.2":"2018-09-17T06:00:03.391Z","0.12.21-alpha.4-testApp.3":"2018-09-17T09:38:15.508Z","0.12.21-alpha.5-testApp.4":"2018-09-17T10:25:12.173Z","0.12.22-alpha.1-homeactivity":"2018-09-21T10:53:22.571Z","0.12.22-alpha.2-homeactivity":"2018-09-25T08:45:40.259Z","0.12.22-alpha.3-homeactivity":"2018-09-25T08:48:53.123Z","0.12.22-alpha.4-testApp.5":"2018-09-25T09:52:32.691Z","0.12.22-alpha.4-homeactivity":"2018-09-25T10:04:20.228Z","0.12.22-alpha.5-testplan.0":"2018-09-27T04:53:19.563Z","0.12.22-alpha.0-graphql":"2018-09-27T07:16:52.218Z","0.12.22-alpha.6-testplan.1":"2018-09-28T07:32:12.470Z","0.12.22-alpha.7-homeactivity":"2018-09-28T09:54:18.007Z","0.12.22":"2018-09-28T10:57:51.333Z","0.12.22-alpha.7-testplan.2":"2018-09-28T12:16:48.714Z","0.12.23-alpha.0-testplan.1":"2018-09-28T12:52:42.438Z","0.12.23-alpha.1-graphql":"2018-09-28T13:34:49.336Z","0.12.23":"2018-09-29T05:34:13.751Z","0.12.24-alpha.0-testhubbyorg":"2018-09-29T09:28:53.176Z","0.12.24":"2018-09-29T09:41:46.448Z","0.12.25-alpha.0-graphqlerrors":"2018-09-30T05:06:45.167Z","0.12.25":"2018-09-30T09:08:00.463Z","0.12.26":"2018-10-08T08:57:36.457Z","0.12.27-alpha.0-dashboardschema":"2018-10-08T15:19:47.507Z","0.12.26-alpha.0-activityteamstyle":"2018-10-09T03:06:26.725Z","0.12.25-alpha.1-teamstyle":"2018-10-09T03:12:14.214Z","0.12.27-alpha.1-role-update":"2018-10-11T04:30:51.308Z","0.12.27-alpha.0-project-schema.2":"2018-10-15T03:50:57.211Z","0.12.27-alpha.0-project-schema.3":"2018-10-15T04:07:28.042Z","0.12.27-alpha.0-project-schema.4":"2018-10-15T10:00:44.054Z","0.12.27-alpha.3-project-schema.4":"2018-10-15T10:19:39.623Z","0.12.27-alpha.4-projectschema":"2018-10-15T11:32:20.654Z","0.12.27-alpha.5-projectportal":"2018-10-15T13:25:37.270Z","0.12.27":"2018-10-17T10:14:46.963Z","0.12.28-alpha.0-testplanid":"2018-10-18T02:13:49.199Z","0.12.28-alpha.1-testplanid":"2018-10-18T02:26:37.477Z","0.12.28":"2018-10-18T02:34:25.798Z","0.6.28":"2018-10-19T07:23:27.132Z","0.12.29":"2018-10-25T00:34:20.132Z","0.12.30":"2018-10-25T13:41:24.772Z","0.12.31-alpha.0-projportal":"2018-10-25T13:46:22.213Z","0.12.31":"2018-10-26T02:28:36.058Z","0.12.32":"2018-10-26T06:57:24.382Z","0.12.33-alpha.0-projschema":"2018-10-26T08:34:04.861Z","0.12.33-alpha.1-polypage":"2018-10-30T01:57:31.986Z","0.12.33-alpha.2-polypage":"2018-10-30T09:39:52.315Z","0.12.33-alpha.3-ts3":"2018-10-30T10:59:14.708Z","0.12.33":"2018-10-30T16:24:52.083Z","0.12.34-alpha.0-perm":"2018-10-30T16:57:46.319Z","0.12.34-alpha.1-rollbackpadding":"2018-10-31T04:24:00.283Z","0.12.32-patch.0-rollbackpadding":"2018-10-31T05:56:59.919Z","0.12.34-alpha.2-rollbackpaddingperm":"2018-10-31T06:58:01.497Z","0.12.34-alpha.3-rollbackpaddingperm":"2018-10-31T12:59:50.238Z","0.12.34-alpha.4-projtaskflow":"2018-11-01T05:06:37.861Z","0.12.34-alpha.5-padding":"2018-11-01T06:01:46.219Z","0.12.34-alpha.6-padding":"2018-11-05T03:35:54.237Z","0.12.34-alpha.7-tapestry":"2018-11-06T09:15:31.227Z","0.12.34-alpha.8-afterpipe":"2018-11-06T12:56:24.538Z","0.12.34":"2018-11-07T06:30:06.690Z","0.12.35-alpha.0-projtagschema":"2018-11-08T11:26:58.205Z","0.12.35-alpha.1-taskdivision":"2018-11-12T08:17:22.150Z","0.12.35-alpha.2-taskdep":"2018-11-12T08:20:07.880Z","0.12.35-alpha.3-polypage":"2018-11-13T03:24:02.753Z","0.12.35":"2018-11-13T07:58:10.977Z","0.12.36":"2018-11-13T10:53:29.722Z","0.12.37-alpha.0-projschema":"2018-11-15T09:50:41.565Z","0.12.37-alpha.1-unknownhomeact":"2018-11-19T03:16:11.847Z","0.12.37-alpha.2-polypage":"2018-11-19T08:15:37.159Z","0.12.34-alpha.8-permbinding":"2018-11-20T07:04:15.002Z","0.12.37-alpha.3-polypage":"2018-11-22T06:27:46.861Z","0.12.37-alpha.4-flowing":"2018-11-22T06:45:28.091Z","0.12.37-alpha.5-sfccf":"2018-11-25T17:29:07.142Z","0.12.37-alpha.6-keepflow":"2018-11-25T17:34:55.449Z","0.12.37":"2018-11-28T03:59:32.444Z","0.12.38":"2018-11-28T09:59:07.133Z","0.12.39-alpha.0-flowthrough":"2018-11-29T00:15:36.249Z","0.12.39":"2018-11-29T12:57:37.296Z","0.12.40-alpha.0-permbinding":"2018-12-05T09:37:50.415Z","0.12.40-alpha.1-luckyflow":"2018-12-06T11:55:09.567Z","0.12.40-alpha.2-projportal":"2018-12-07T12:08:24.995Z","0.12.40-alpha.3-objecttype":"2018-12-10T02:34:46.635Z","0.12.40-alpha.4":"2018-12-10T03:49:57.442Z","0.12.38-patch.0-tasklistvis":"2018-12-11T05:52:07.115Z","0.12.40-alpha.4-testplan":"2018-12-14T08:29:48.136Z","0.12.40-alpha.5-smartgroup":"2018-12-17T02:09:36.944Z","0.12.40":"2018-12-17T02:51:39.591Z","0.12.41-alpha.0-smartgroup":"2018-12-17T03:22:45.652Z","0.12.41-alpha.1-testplan":"2018-12-18T06:41:58.862Z","0.12.41-alpha.2-testplan":"2018-12-18T08:55:58.616Z","0.12.41-alpha.3-smartgroup":"2018-12-19T09:47:03.212Z","0.12.41-alpha.4-projcluster":"2018-12-19T10:24:56.444Z","0.12.41-alpha.5-flowboard":"2018-12-20T05:41:17.511Z","0.12.41-alpha.4-smartgroup":"2018-12-20T13:48:52.832Z","0.12.41-alpha.6-smartgroup":"2018-12-20T14:00:00.092Z","0.12.41-alpha.7-smartgroup":"2018-12-21T03:06:09.532Z","0.12.41-alpha.8-tapestry":"2018-12-26T05:34:26.781Z","0.12.41":"2018-12-26T08:45:52.892Z","0.12.42-alpha.0-polypage":"2018-12-26T09:19:21.241Z","0.12.41-alpha.9-projportal":"2018-12-26T10:25:18.685Z","0.12.42-alpha.1-testplan":"2018-12-26T12:45:52.306Z","0.12.42-alpha.2-smartgroup":"2018-12-27T06:18:06.717Z","0.12.42-alpha.3-smartgroup":"2018-12-29T07:09:25.950Z","0.12.42":"2019-01-03T07:30:50.745Z","0.12.43":"2019-01-03T08:09:47.255Z","0.12.44-alpha.0-smartgroup":"2019-01-03T12:00:40.766Z","0.12.44-alpha.1-tapboard":"2019-01-04T09:52:52.033Z","0.12.44-alpha.2-testcase":"2019-01-08T03:39:33.068Z","0.12.44-alpha.3-sfcf":"2019-01-08T12:59:04.583Z","0.12.44-alpha.4-sfcf":"2019-01-09T05:42:15.123Z","0.12.44":"2019-01-09T08:33:09.720Z","0.12.45-alpha.0-smartgroup":"2019-01-10T06:10:19.502Z","0.12.45-alpha.1-sfcf":"2019-01-14T11:48:53.786Z","0.12.45-alpha.2-sfcf":"2019-01-15T05:28:26.315Z","0.12.45-alpha.3-commongroup":"2019-01-16T09:31:17.673Z","0.12.45":"2019-01-17T03:10:40.044Z","0.12.45-alpha.4-scenariofield":"2019-01-17T03:58:33.919Z","0.12.45-alpha.5-scenariofield":"2019-01-17T04:21:37.284Z","0.12.45-alpha.6-scenariofield":"2019-01-17T04:31:21.899Z","0.12.46-alpha.0-prefmd":"2019-01-18T06:12:22.513Z","0.12.46-alpha.1-cgcf":"2019-01-18T06:24:23.369Z","0.12.46-alpha.2-smartgroup":"2019-01-21T03:05:15.302Z","0.12.46-alpha.3-scenariofield":"2019-01-21T03:47:52.384Z","0.12.46-alpha.4-tapestry":"2019-01-21T06:08:05.144Z","0.12.46-alpha.5-prefmd":"2019-01-22T03:53:40.394Z","0.12.46-alpha.6-tapestry":"2019-01-22T09:49:14.818Z","0.12.46-alpha.7-cgcf":"2019-01-23T06:11:18.851Z","0.12.46":"2019-01-23T10:01:59.260Z","0.12.47":"2019-01-23T11:09:11.941Z","0.12.48-alpha.0-projsrcid":"2019-01-24T02:21:02.497Z","0.12.46-alpha.8-projsrcid":"2019-01-25T06:00:27.728Z","0.12.48":"2019-01-28T06:34:47.702Z","0.12.49-alpha.0-smartgroup":"2019-01-28T15:10:42.069Z","0.12.49-alpha.1-smartgroup":"2019-01-28T15:13:56.653Z","0.12.49-alpha.2-cfcg":"2019-01-31T06:46:14.562Z","0.12.49":"2019-02-01T02:02:14.392Z","0.12.50-alpha.0-pagepost":"2019-02-01T06:05:01.577Z","0.12.50-alpha.1-cflock":"2019-02-01T06:08:27.456Z","0.12.50-alpha.2-cflock":"2019-02-01T08:09:15.891Z","0.12.50-alpha.3-cflock":"2019-02-01T10:29:35.436Z","0.12.50-alpha.4-cgcf":"2019-02-01T11:14:20.464Z","0.12.50-alpha.4-cflock":"2019-02-01T11:39:44.690Z","0.6.29":"2019-02-12T07:48:31.628Z","0.12.50-alpha.5-cfsingle":"2019-02-13T10:45:13.259Z","0.12.50-alpha.6-cfsingle":"2019-02-13T11:18:55.158Z","0.12.50":"2019-02-14T02:33:34.206Z","0.12.50-alpha.7-cflock":"2019-02-14T05:23:28.172Z","0.12.50-alpha.8-cflock":"2019-02-14T06:57:24.106Z","0.12.51-alpha.0-idb":"2019-02-14T11:05:52.702Z","0.12.51-alpha.1-idb":"2019-02-14T11:29:44.259Z","0.12.51-alpha.2-smartgroup":"2019-02-18T03:23:34.819Z","0.12.51-alpha.3-cflock":"2019-02-18T03:30:15.671Z","0.12.51":"2019-02-18T10:46:17.344Z","0.12.52-alpha.0-cgcf":"2019-02-18T11:35:08.873Z","0.12.52":"2019-02-20T09:07:52.909Z","0.12.53-alpha.0-idb":"2019-02-20T09:40:29.554Z","0.12.53-alpha.1-idb":"2019-02-20T12:28:02.290Z","0.12.53-alpha.2-smartgroup":"2019-02-20T13:21:38.918Z","0.12.53-alpha.3-consumerid":"2019-02-21T15:31:27.500Z","0.12.53-alpha.4-consumerid":"2019-02-21T15:45:43.583Z","0.12.53-alpha.5-graphql":"2019-02-22T05:49:00.034Z","0.12.53-alpha.6-tapestry":"2019-02-28T05:54:00.198Z","0.12.53":"2019-03-01T09:35:09.837Z","0.12.54-alpha.0-tapestry":"2019-03-06T06:39:51.372Z","0.12.54-alpha.1-project":"2019-03-06T10:19:47.773Z","0.12.54-alpha.2-idb":"2019-03-06T11:40:21.794Z","0.12.54-alpha.3-smartgroup":"2019-03-07T06:23:43.446Z","0.12.54-alpha.4-smartgroup":"2019-03-07T06:56:24.107Z","0.12.54-alpha.5-padding":"2019-03-08T06:25:41.840Z","0.12.54-alpha.6-smartgroup":"2019-03-12T07:00:52.006Z","0.12.54-alpha.7-projtag":"2019-03-12T08:45:52.679Z","0.12.54":"2019-03-12T08:52:56.591Z","0.12.55-alpha.0-useropenid":"2019-03-13T09:37:57.875Z","0.12.55-alpha.1-gaone":"2019-03-13T10:01:29.275Z","0.12.55-alpha.2-idb":"2019-03-13T10:03:43.116Z","0.12.55-alpha.3-ga":"2019-03-13T12:06:52.772Z","0.12.55-alpha.4-smartgroup":"2019-03-13T12:11:57.779Z","0.12.55-alpha.5-dedupmapfn":"2019-03-15T00:51:24.995Z","0.12.55-alpha.6-gaone":"2019-03-15T03:43:30.975Z","0.12.55-alpha.7-projtag":"2019-03-15T04:08:07.043Z","0.12.55":"2019-03-15T06:15:28.181Z","0.12.55-alpha.8-graphql":"2019-03-20T08:49:46.478Z","0.12.56-alpha.0-ga":"2019-03-20T08:58:28.132Z","0.12.55-alpha.9-projtag":"2019-03-20T09:03:52.382Z","0.12.55-alpha.10-useropenid":"2019-03-20T09:13:06.564Z","0.12.55-alpha.11-idb":"2019-03-20T09:25:13.876Z","0.12.55-alpha.12-smartgroup":"2019-03-20T09:29:23.877Z","0.12.56-alpha.1-taskprivilege":"2019-03-21T10:48:54.358Z","0.12.56-alpha.2-project":"2019-03-22T04:19:46.435Z","0.12.56-alpha.3-gaone":"2019-03-25T07:34:18.178Z","0.12.55-alpha.13-aone":"2019-03-25T07:59:46.537Z","0.12.56-alpha.4-sfcpaddingcustomfield":"2019-04-01T12:08:11.776Z","0.12.56-alpha.5-sfcpaddingcustomfield":"2019-04-02T03:56:00.866Z","0.12.56-alpha.6-sfcpaddingcustomfield":"2019-04-03T05:07:14.225Z","0.12.56":"2019-04-03T07:24:09.482Z","0.12.57-alpha.0-consumerid":"2019-04-03T07:46:08.153Z","0.12.56-alpha.7-sfcf":"2019-04-08T03:05:14.630Z","0.12.57":"2019-04-08T07:05:47.669Z","0.12.56-alpha.8-ptagvis":"2019-04-09T09:32:17.287Z","0.12.58-alpha.0-ptagvis":"2019-04-11T08:12:45.111Z","0.12.58":"2019-04-15T04:14:43.840Z","0.12.59-alpha.0-sfroleids":"2019-04-17T10:12:37.300Z","0.12.59-alpha.1-sfroleids":"2019-04-18T06:08:35.405Z","0.12.59-alpha.2-taskwithtaskflowstatus":"2019-04-26T03:45:19.910Z","0.12.59-alpha.3-pcount":"2019-05-06T00:56:41.292Z","0.12.59-alpha.4-pcount":"2019-05-07T09:02:45.060Z","0.12.59-alpha.5-currprojcount":"2019-05-08T03:40:41.252Z","0.12.59-beta.0-ga":"2019-05-08T03:49:45.789Z","0.12.59-alpha.6-pcount":"2019-05-08T07:13:33.778Z","0.12.59-beta.1-ga":"2019-05-08T07:19:45.445Z","0.12.59-beta.2-ga":"2019-05-08T07:29:45.744Z","0.12.59-alpha.7-cfvalue":"2019-05-09T10:49:18.731Z","0.12.59":"2019-05-15T01:11:56.249Z","0.12.60-alpha.0-cfvalue":"2019-05-15T06:19:47.014Z","0.12.60-alpha.1-cfvalue":"2019-05-15T07:08:56.544Z","0.12.60-alpha.2-cfvalue":"2019-05-15T08:53:58.758Z","0.12.60-alpha.3-tapestry":"2019-05-16T08:46:55.723Z","0.12.60-alpha.4-httperr":"2019-05-20T01:32:31.059Z","0.12.60-alpha.5-httperr":"2019-05-20T01:43:49.003Z","0.12.60-beta.0-ga":"2019-05-22T07:34:34.577Z","0.12.60":"2019-05-23T02:46:57.637Z","0.12.61-beta.0-ga":"2019-05-23T03:14:20.224Z","0.12.62-alpha.0-tapestry":"2019-05-24T05:32:09.859Z","0.12.62-alpha.1-tapestry":"2019-05-24T05:40:08.301Z","0.12.62-alpha.2-tapestry":"2019-05-24T06:09:03.784Z","0.12.62-alpha.3-scenariofieldconfigspagesize":"2019-05-29T05:38:13.246Z","0.12.62-alpha.4-scenariofieldconfigspagesize":"2019-05-29T05:44:55.935Z","0.12.62-alpha.5-scenariofieldconfigspagesize":"2019-05-29T13:50:48.202Z","0.12.61":"2019-05-30T05:30:42.056Z","0.12.62-alpha.6-tboardrev":"2019-06-04T09:45:47.914Z","0.12.62-alpha.7-tboardrev":"2019-06-05T02:17:45.293Z","0.12.62-alpha.8-tapestry":"2019-06-05T02:40:32.757Z","0.12.62-beta.0":"2019-06-05T08:09:53.440Z","0.12.62-alpha.9-tboardrev":"2019-06-06T05:46:22.933Z","0.12.62-alpha.10-task":"2019-06-10T07:46:18.916Z","0.12.62-alpha.11-suspendproj":"2019-06-12T09:24:45.527Z","0.12.62-alpha.12-tapchartname":"2019-06-14T03:49:40.594Z","0.12.62-alpha.13-tapchartname":"2019-06-14T06:05:15.325Z","0.12.63-alpha.14-tapsus":"2019-06-14T07:39:32.644Z","0.12.62-alpha.14-tapsus":"2019-06-14T07:45:55.390Z","0.12.62-beta.1":"2019-06-19T04:15:03.548Z","0.12.62-beta.2":"2019-06-19T04:21:40.991Z","0.12.62-alpha.15-projsus":"2019-06-19T09:34:50.291Z","0.12.62-beta.3":"2019-06-19T11:10:10.092Z","0.12.63-alpha.15-tasksortmethod":"2019-06-25T02:46:55.078Z","0.12.62":"2019-06-27T02:25:29.911Z","0.12.63-alpha.16-alihttperr":"2019-06-27T02:28:25.457Z","0.12.63-alpha.17-alihttperr":"2019-06-27T08:10:40.185Z","0.12.63-alpha.18-cfe":"2019-06-27T13:17:46.304Z","0.12.63-alpha.19-cfe":"2019-07-01T01:15:30.311Z","0.12.63-alpha.20-alihttperr":"2019-07-01T06:39:40.816Z","0.12.63-beta.0":"2019-07-03T06:41:23.683Z","0.12.63-beta.1-consumerid":"2019-07-04T07:18:45.536Z","0.12.63":"2019-07-09T05:47:12.563Z","0.12.64-alpha.0-ievent":"2019-07-09T05:49:12.347Z","0.12.64-alpha.1-smartgroup":"2019-07-10T07:23:02.116Z","0.12.64-alpha.2-sfe":"2019-07-10T07:29:17.878Z","0.12.64-alpha.3-sfe":"2019-07-10T07:37:54.163Z","0.12.50-alpha.9-sfcf":"2019-07-12T07:13:56.709Z","0.12.64-alpha.4-bulkaddscenariofields":"2019-07-12T10:52:19.141Z","0.12.64-alpha.5-ievent":"2019-07-15T07:23:56.674Z","0.12.64-alpha.6-sfe":"2019-07-16T13:49:08.599Z","0.12.64-alpha.7-pstatusname":"2019-07-17T05:44:38.270Z","0.12.64-beta.0":"2019-07-17T09:20:00.975Z","0.12.64-beta.1":"2019-07-17T09:42:16.023Z","0.12.64-alpha.8-bulkaddscenariofields":"2019-07-17T09:56:58.509Z","0.12.64-alpha.9-pstatusname":"2019-07-17T10:11:47.480Z","0.12.64-alpha.10-ievent":"2019-07-17T10:18:00.036Z","0.12.64-beta.2":"2019-07-19T09:20:02.575Z","0.12.64-alpha.11-pstatusdegree":"2019-07-22T09:25:22.920Z","0.12.65-alpha.0-sfe":"2019-07-23T07:07:35.758Z","0.12.64":"2019-07-24T10:23:11.378Z","0.12.65-alpha.1-ptemp":"2019-07-25T08:11:28.866Z","0.12.65-alpha.2-sfe":"2019-07-25T10:46:18.493Z","0.12.65-alpha.3-smartgroupviewtasklayer":"2019-07-26T03:01:12.808Z","0.12.65-alpha.4-projschema":"2019-07-30T10:02:16.785Z","0.12.65-alpha.5-sfe":"2019-07-31T06:59:34.893Z","0.12.65-beta.0":"2019-07-31T10:21:26.936Z","0.12.66-alpha.0-smartgroupviewtasklayer":"2019-08-01T02:55:00.123Z","0.12.66-alpha.1-smartgroupviewtasklayer":"2019-08-01T03:16:21.801Z","0.12.66-alpha.2-asyncdbleakage":"2019-08-05T03:38:59.985Z","0.12.66-alpha.3-projschema":"2019-08-05T06:13:07.616Z","0.12.65":"2019-08-07T02:41:20.512Z","0.12.66-alpha.4-projschema":"2019-08-08T06:48:45.134Z","0.12.66-alpha.5-smartgroupviewtasklayer":"2019-08-08T07:31:57.422Z","0.12.66-alpha.6-projschema":"2019-08-13T03:32:20.195Z","0.12.66":"2019-08-14T07:48:58.844Z","0.12.67-beta.0-fetchshare":"2019-08-14T08:46:22.294Z","0.12.67":"2019-08-22T06:52:11.770Z","0.12.68-alpha.1-batch":"2019-08-22T07:15:54.344Z","0.12.68-alpha.2-customfieldsubtype":"2019-08-28T03:06:07.236Z","0.12.68-alpha.3-batch":"2019-08-28T03:18:25.994Z","0.12.68":"2019-08-28T03:45:31.823Z","0.12.69-alpha.0-batch":"2019-08-29T06:45:19.964Z","0.12.69-alpha.1-sfc":"2019-08-30T08:52:59.774Z","0.12.69-alpha.2-batch":"2019-09-02T06:26:01.366Z","0.12.69-alpha.3-cascading":"2019-10-08T10:04:06.846Z","0.12.69-alpha.4-tapestry":"2019-10-09T09:53:10.986Z","0.12.69-alpha.5-projcustomview":"2019-10-15T10:04:44.868Z","0.12.69-alpha.6-cascading":"2019-10-16T11:33:03.794Z","0.12.69-alpha.7-cascading":"2019-10-16T12:07:30.372Z","0.12.69-alpha.8-cascading":"2019-10-17T04:37:50.493Z","0.12.69-alpha.9-perms":"2019-10-17T06:26:31.541Z","0.12.69-alpha.10-cascading":"2019-10-17T15:09:55.570Z","0.12.69-alpha.11-tagids":"2019-10-18T09:06:51.929Z","0.12.69-alpha.11-cascading":"2019-10-22T03:46:56.670Z","0.12.69":"2019-10-23T03:37:25.694Z","0.12.70-alpha.0-cascading":"2019-10-23T05:52:23.334Z","0.12.70-alpha.1-projcustomview":"2019-10-23T08:27:57.152Z","0.12.70-alpha.2-robotactivity":"2019-10-24T02:29:06.241Z","0.12.70-alpha.3-batch":"2019-10-24T03:54:12.397Z","0.12.70-alpha.4-tagids":"2019-10-24T04:05:13.247Z","0.12.70-alpha.5-projcustomview":"2019-10-28T07:34:49.023Z","0.12.70-alpha.6-customviewoptions":"2019-10-28T08:19:04.500Z","0.12.70-alpha.7-customview":"2019-10-28T08:21:51.627Z","0.12.70-alpha.8-projcustomview":"2019-10-28T10:17:06.700Z","0.12.70-alpha.9-customview":"2019-10-28T10:19:12.631Z","0.12.70-alpha.10-projtempl":"2019-10-29T05:33:24.461Z","0.12.70":"2019-10-29T13:28:48.187Z","0.12.71-alpha.0-cascading":"2019-10-30T02:48:53.192Z","0.12.71-alpha.1-tagids":"2019-10-30T03:00:07.035Z","0.12.71-alpha.2-customviewoptions":"2019-10-30T03:11:29.954Z","0.12.71-alpha.3-projcustomview":"2019-10-30T03:15:18.492Z","0.12.71-alpha.4-customviewoption":"2019-10-30T08:26:53.218Z","0.12.71-alpha.5-tagids":"2019-10-30T11:36:33.047Z","0.12.71-alpha.6-cascading":"2019-10-30T12:16:53.165Z","0.12.71-alpha.7-batch":"2019-10-31T02:59:16.711Z","0.12.71-alpha.8-customviewoption":"2019-10-31T09:42:27.546Z","0.12.71-alpha.9-projtempl":"2019-11-01T03:15:05.769Z","0.12.71-alpha.10-tapestry":"2019-11-04T07:35:49.440Z","0.12.71-alpha.10-setmethods":"2019-11-05T01:50:51.344Z","0.12.71-alpha.10-tableseethroughsubtasks":"2019-11-05T02:38:58.615Z","0.12.71-alpha.11-tableseethroughsubtasks":"2019-11-05T03:27:21.844Z","0.12.71-alpha.10-fetchclient":"2019-11-05T08:48:59.748Z","0.12.71-alpha.10-fetchclient.1":"2019-11-05T08:55:22.203Z","0.12.71":"2019-11-08T10:40:11.124Z","0.12.72-alpha.0-tapestry":"2019-11-08T10:43:18.309Z","10.12.72-alpha.1-sfpresets":"2019-11-11T03:13:17.581Z","0.12.71-alpha.10-fetchclient.3":"2019-11-12T02:01:27.613Z","0.12.71-alpha.10-fetchclient.5":"2019-11-12T02:35:58.316Z","0.12.72-alpha.2-sfpresets":"2019-11-13T08:17:45.741Z","0.12.72-alpha.3-tapestry":"2019-11-13T09:08:20.248Z","0.12.72-alpha.4-tableseethroughsubtasks":"2019-11-13T09:29:05.004Z","0.12.72-alpha.5-projtempl":"2019-11-13T09:58:01.889Z","0.12.72-alpha.6-sfpresets":"2019-11-13T12:27:16.160Z","0.12.72-alpha.7-fetchclient":"2019-11-14T06:44:43.565Z","0.12.72-alpha.9-batch":"2019-11-19T06:45:02.319Z","0.12.72-alpha.10-unftitle":"2019-11-20T07:28:32.488Z","0.12.72":"2019-11-27T10:56:04.969Z","0.12.73-alpha.0-batch":"2019-11-27T10:59:26.823Z","0.12.73-alpha.1-setHttpMethod":"2019-11-28T06:12:17.597Z","0.12.73-alpha.2-assignlinks":"2019-12-06T10:45:18.189Z","0.12.73-alpha.3-axistype":"2019-12-08T07:00:43.475Z","0.12.73-alpha.4-assignment":"2019-12-09T03:00:35.422Z","0.12.73-alpha.5-assignment":"2019-12-09T04:00:49.196Z","0.12.73-alpha.6-assignment":"2019-12-10T02:18:31.797Z","0.12.73-alpha.7-lagtime":"2019-12-10T09:50:24.582Z","0.12.73-alpha.8-flowstatus":"2019-12-11T04:04:35.632Z","0.12.73-alpha.9-flowstatus":"2019-12-11T07:32:32.125Z","0.12.73-alpha.10-priority":"2019-12-12T03:47:13.613Z","0.12.73-alpha.11-milestone":"2019-12-12T06:29:10.874Z","0.12.73-alpha.12-assignment":"2019-12-13T02:34:53.321Z","0.12.73-alpha.10-setHttpMethods":"2019-12-17T03:03:33.239Z","0.12.73-alpha.13-assignment":"2019-12-17T03:45:30.788Z","0.12.73-alpha.14-milestone.and.lagtime":"2019-12-17T11:18:02.498Z","0.12.73-alpha.15-batch":"2019-12-18T08:24:43.461Z","0.12.73-alpha.16-analytics":"2019-12-20T09:31:51.194Z","0.12.73-alpha.16-assignment":"2019-12-24T07:04:03.620Z","0.12.73-beta.0":"2019-12-25T09:01:50.403Z","0.12.73-beta.1":"2019-12-25T10:44:51.242Z","0.12.73-beta.2-sethttpmethod":"2019-12-25T13:30:00.646Z","0.12.73-beta.2":"2019-12-27T10:28:28.822Z","0.12.74-alpha.0-sethttpmethod":"2020-01-05T07:18:48.920Z","0.12.74-alpha.1-milestone":"2020-01-06T08:48:03.666Z","0.12.74-alpha.2-milestone":"2020-01-07T03:59:30.367Z","0.12.73":"2020-01-16T00:56:44.610Z","0.12.74":"2020-01-16T01:05:08.085Z","0.12.74-alpha.3-approval":"2020-01-19T09:38:57.008Z","0.12.75-alpha.0-sprint":"2020-01-21T00:35:31.580Z","0.12.75-alpha.1-sprint":"2020-01-22T04:33:53.097Z","0.12.75-alpha.2-approval":"2020-02-01T06:22:44.334Z","0.12.75-alpha.3-approval":"2020-02-03T06:55:29.861Z","0.12.75-alpha.4-taskpos":"2020-02-04T02:04:10.926Z","0.12.75-alpha.5-taskpos":"2020-02-07T07:52:36.884Z","0.12.75-beta.0":"2020-02-12T08:20:03.697Z","0.12.75-beta.1-taskpos":"2020-02-12T08:24:01.164Z","0.12.75":"2020-02-24T02:15:21.754Z","0.12.76-alpha.0-customapp":"2020-02-24T02:18:24.319Z","0.12.76-alpha.1-taskpos":"2020-02-24T03:01:09.228Z","0.12.76-alpha.2-analytics":"2020-02-25T01:23:34.226Z","0.12.76-alpha.3-analytics":"2020-02-25T02:56:59.476Z","0.12.76-alpha.4-customapp":"2020-02-25T09:00:19.916Z","0.12.76-beta.0":"2020-02-26T06:08:19.282Z","0.12.76":"2020-03-05T00:57:35.517Z","0.12.77-alpha.0-customprojectrole":"2020-03-09T03:09:31.099Z","0.12.77-alpha.1-scenariosetting":"2020-03-10T02:45:00.519Z","0.12.77-alpha.2-workcal":"2020-03-10T07:27:39.633Z","0.12.77-alpha.3-scenariosetting":"2020-03-10T07:39:53.947Z","0.12.77-alpha.4-scenariosetting":"2020-03-11T12:12:13.632Z","0.12.77-alpha.5-priority":"2020-03-13T08:56:38.316Z","0.12.77-alpha.6-dinganalytics":"2020-03-17T02:29:47.915Z","0.12.77-alpha.7-workcal":"2020-03-17T09:00:47.224Z","0.12.77-alpha.8.priority":"2020-03-18T02:44:47.038Z","0.12.77-alpha.9-memberidentity":"2020-03-18T03:06:58.387Z","0.12.77-alpha.10-workcal":"2020-03-18T09:50:06.708Z","0.12.77-alpha.11-memberidentity":"2020-03-19T10:08:28.397Z","0.12.77-alpha.12-workcal":"2020-03-19T10:13:28.740Z","0.12.77":"2020-03-20T09:02:41.304Z","0.12.78-alpha.0-aonesrc":"2020-03-20T09:04:42.630Z","0.12.78-alpha.1-memberidentity":"2020-03-25T05:42:00.357Z","0.12.78-alpha.2-priority":"2020-03-25T05:45:43.508Z","0.12.78-alpha.3-workcal":"2020-03-25T05:56:55.017Z","0.12.78-alpha.4-dinganalytics":"2020-03-25T09:54:07.544Z","0.12.78-alpha.5-testcasecustomfield":"2020-03-26T08:10:37.410Z","0.12.79-alpha.0-testcasecustomfield":"2020-03-26T09:05:37.555Z","0.12.79-alpha.1-testcasecustomfield":"2020-03-30T03:55:09.416Z","0.12.78":"2020-03-31T14:39:18.629Z","0.12.79-alpha.2-aonesrc":"2020-04-02T06:09:33.543Z","0.12.79-alpha.3-kanbanconfig":"2020-04-07T01:49:02.379Z","0.12.79-beta.0-testcasecustomfield":"2020-04-08T08:44:55.072Z","0.12.79-beta.1-kanbanconfig":"2020-04-08T08:51:25.779Z","0.12.79-beta.2-aonesrc":"2020-04-10T02:50:23.451Z","0.12.79-beta.3-commongroupchoices":"2020-04-10T03:27:31.135Z","0.12.80-alpha.0-taskurge":"2020-04-13T06:59:29.492Z","0.12.80-alpha.1-taskurge":"2020-04-13T07:27:40.345Z","0.12.80-alpha.2-taskurge":"2020-04-13T07:51:03.638Z","0.12.79-beta.4-commongroupchoices":"2020-04-14T04:00:08.279Z","0.12.79-beta.5-commongroupchoices":"2020-04-14T04:27:59.321Z","0.12.79-beta.6-commongroupchoices":"2020-04-14T05:11:33.268Z","0.12.79-beta.7-commongroupchoices":"2020-04-14T06:01:59.037Z","0.12.80-alpha.3-taskurge":"2020-04-15T10:38:38.713Z","0.12.79":"2020-04-16T02:53:55.240Z","0.12.80":"2020-04-16T03:12:50.791Z","0.12.81":"2020-04-16T03:22:02.584Z","0.12.79-beta.4":"2020-04-16T06:37:28.437Z","0.12.82":"2020-04-17T03:26:39.087Z","0.12.83-alpha.0-customportal":"2020-04-17T03:30:40.399Z","0.12.80-alpha.4-taskurge":"2020-04-17T05:49:54.793Z","0.12.83-alpha.0-taskurge":"2020-04-20T02:57:56.362Z","0.12.84-alpha.0-tasktrace":"2020-04-21T07:19:48.018Z","0.12.84-alpha.1-tasktrace":"2020-04-21T08:16:56.835Z","0.12.84-alpha.2-tasktrace":"2020-04-21T09:28:09.878Z","0.12.84-alpha.3-tasktrace":"2020-04-21T10:28:14.061Z","0.12.83-alpha.1-kanbanconfig":"2020-04-21T12:50:20.558Z","0.12.83-beta.0-taskurge":"2020-04-22T08:15:56.498Z","0.12.84-alpha.4-tasktrace":"2020-04-23T07:04:00.602Z","0.12.84-alpha.5-tasktrace":"2020-04-27T07:31:18.518Z","0.12.83-alpha.2-kanbanconfig":"2020-04-27T08:31:59.169Z","0.12.83":"2020-04-29T11:35:28.500Z","0.12.84-alpha.6-customportal":"2020-04-30T05:44:19.212Z","0.12.84-alpha.7-tasktrace":"2020-05-07T05:20:12.346Z","0.12.84-alpha.8-tasktrace":"2020-05-09T04:08:11.770Z","0.12.84-alpha.9-tasktrace":"2020-05-09T05:49:53.194Z","0.12.84-alpha.10-tasktrace":"2020-05-09T06:02:43.602Z","0.12.84-alpha.11-tasktrace":"2020-05-09T06:40:53.537Z","0.12.84-alpha.12-tasktrace":"2020-05-09T08:47:13.048Z","0.12.84-beta.0-kanbanconfig":"2020-05-13T04:02:41.772Z","0.12.84-beta.1-customportal":"2020-05-13T08:17:39.145Z","0.12.84-beta.2-tasktrace":"2020-05-13T11:17:23.862Z","0.12.85-alpha.0-tasktraceobjecttype":"2020-05-14T08:21:59.832Z","0.12.85-alpha.1-tasktraceobjecttype":"2020-05-14T11:31:33.564Z","0.12.85-alpha.2-workcal":"2020-05-18T09:04:35.809Z","0.12.85-alpha.3-tasktraceobjecttype":"2020-05-18T17:14:44.441Z","0.12.85-alpha.4-tasktraceobjecttype":"2020-05-19T12:35:16.779Z","0.12.85-alpha.5-tasktraceobjecttype":"2020-05-19T14:46:44.230Z","0.12.85-alpha.6-taskrelations":"2020-05-19T18:54:24.967Z","0.12.85-alpha.7-taskrelations":"2020-05-20T02:43:19.605Z","0.12.85-alpha.8-taskrelations":"2020-05-20T07:17:46.411Z","0.12.85-alpha.9-taskreminders":"2020-05-22T09:47:21.175Z","0.12.85-alpha.10-taskrelations":"2020-05-26T06:03:13.562Z","0.12.85-alpha.11-taskreminders":"2020-05-27T05:56:55.103Z","0.12.85-alpha.12-taskreminders":"2020-05-27T06:50:50.132Z","0.12.84":"2020-05-27T07:00:01.730Z","0.12.85-beta.0-taskreminders":"2020-05-27T08:07:31.134Z","0.12.85-beta.1-tasktraceobjecttype":"2020-05-27T09:02:23.372Z","0.12.85-beta.2":"2020-05-27T10:02:51.384Z","0.12.86-alpha.0-taskrelations":"2020-05-28T03:04:46.389Z","0.12.86-alpha.1-sfcbasicfields":"2020-05-28T04:52:22.061Z","0.12.86-alpha.2-sfcbasicfields":"2020-05-28T09:25:37.119Z","0.12.86-alpha.3-subtasksfcids":"2020-06-03T03:00:54.039Z","0.12.85":"2020-06-03T07:25:31.175Z","0.12.86-alpha.4-subtasksfcids":"2020-06-03T09:38:52.788Z","0.12.86-alpha.5-task-relations":"2020-06-05T09:12:55.711Z","0.12.86-alpha.6-task-relations":"2020-06-09T07:59:21.291Z","0.12.86-beta.0":"2020-06-10T09:33:03.882Z","0.12.87-alpha.0-sfcbasicfields":"2020-06-15T07:09:27.915Z","0.12.86":"2020-06-17T10:14:24.994Z","0.12.87-alpha.1-analytics":"2020-06-22T11:12:44.840Z","0.12.87-alpha.2-customfieldname":"2020-06-23T04:56:25.085Z","0.12.87-alpha.3-orgplan":"2020-06-24T03:36:41.613Z","0.12.87-beta.0-sfcbasicfields":"2020-06-24T04:53:37.316Z","0.12.87-beta.1-customfieldname":"2020-06-24T05:49:18.707Z","0.12.87-beta.2-analytics":"2020-06-24T05:55:48.820Z","0.12.87-beta.3-analytics":"2020-06-30T08:09:15.419Z","0.12.88-alpha.0-orgplan":"2020-07-01T05:43:52.443Z","0.12.88-alpha.1-orgplan":"2020-07-02T14:35:23.816Z","0.12.87":"2020-07-07T03:03:09.732Z","0.12.87-alpha.0-personalorg":"2020-07-31T14:37:30.711Z","0.12.87-alpha.1-personalorg":"2020-08-03T08:31:54.767Z","0.12.87-alpha.1-projectreminder":"2020-08-06T08:34:45.733Z","0.12.88":"2020-08-07T04:38:22.263Z","0.12.89":"2020-08-07T09:28:20.082Z","0.12.89-alpha.0-kanbanconfig":"2020-09-01T02:48:39.236Z","0.12.89-alpha.1-kanbanconfig":"2020-09-01T03:06:23.773Z","0.12.89-alpha.2-kanbanconfig":"2020-09-01T03:21:49.911Z","0.12.90-alpha.0-analytics":"2020-09-08T02:21:26.209Z","0.12.90-alpha.1-orgschema":"2020-09-14T09:45:00.283Z","0.12.90-alpha.2-orgschema":"2020-09-17T11:24:09.585Z","0.12.90":"2020-09-23T04:24:55.771Z","0.12.91-alpha.0-work":"2020-11-27T02:36:28.380Z","0.12.91-alpha.1-cf":"2020-12-01T12:35:34.961Z","0.12.91-alpha.2-cf":"2020-12-03T05:59:34.027Z","0.12.91-alpha.3-cf":"2020-12-10T03:16:41.746Z","0.12.91-alpha.4-cf":"2020-12-10T03:21:12.838Z","0.12.91-alpha.5-cf":"2020-12-10T06:08:10.966Z","0.12.91-alpha.6-smartgroup":"2020-12-21T08:53:56.125Z","0.12.91-alpha.7-smartgroup":"2020-12-24T12:58:22.765Z","0.12.91-alpha.8-smartgroup":"2020-12-29T12:08:31.507Z","0.12.91-alpha.6":"2021-01-05T02:49:52.673Z","0.12.91-alpha.8-pos":"2021-01-18T06:36:03.913Z","0.12.91-alpha.9-pos":"2021-01-18T06:47:29.914Z","0.12.91-alpha.10-prole":"2021-02-04T02:11:14.478Z","0.12.91-alpha.11-preference":"2021-02-07T03:57:36.299Z","0.12.91-alpha.13-prole":"2021-02-10T06:58:04.479Z","0.12.91-alpha.15":"2021-03-02T06:51:11.477Z","0.12.91-alpha.16":"2021-03-05T03:31:05.923Z","0.12.91-alpha.17":"2021-03-12T10:12:00.684Z","0.12.91":"2021-03-24T09:14:30.277Z","0.12.92-alpha.0":"2021-03-24T10:58:14.854Z","0.12.92-alpha.1":"2021-03-24T11:13:59.471Z","0.12.92-alpha.2":"2021-03-25T08:26:10.558Z","0.12.91-alpha.18":"2021-04-06T03:03:52.827Z","0.12.91-alpha.19":"2021-04-06T03:30:17.327Z","0.12.91-alpha.20":"2021-04-08T09:36:47.970Z","0.12.92-alpha.3":"2021-04-14T02:37:34.185Z","0.12.92-alpha.4":"2021-04-28T12:27:39.202Z","0.12.92-alpha.5":"2021-04-30T06:30:17.217Z","0.12.92-alpha.6":"2021-04-30T07:34:49.273Z","0.12.92-alpha.3-sunburst":"2021-05-07T03:02:42.716Z","0.12.92-alpha.4-sunburst":"2021-05-07T03:34:34.500Z","0.12.92":"2021-05-10T06:19:55.725Z","0.12.93-alpha.0":"2021-05-10T11:41:25.322Z","0.12.93-alpha.1":"2021-05-21T09:46:34.190Z","0.12.93-alpha.2":"2021-05-21T12:05:23.252Z","0.12.93":"2021-07-01T07:19:14.772Z","0.12.94-alpha.0":"2021-10-09T07:36:50.676Z","0.12.94-alpha.1":"2021-10-09T08:08:53.484Z","0.12.94-alpha.2":"2022-04-26T00:53:12.748Z","0.12.95-alpha.0-smartgroup":"2022-06-08T12:16:09.337Z","0.12.95-alpha.1-smartgroup":"2022-06-09T08:01:01.470Z","0.12.95-alpha.2-smartgroup":"2022-06-15T06:29:07.022Z","0.12.95-alpha.3-smartgroup":"2022-06-16T02:20:26.834Z","0.12.95-alpha.4-sfcv2":"2022-06-21T08:10:42.550Z","0.12.95-alpha.5-tasklist":"2022-06-23T08:23:32.180Z","0.12.94":"2022-06-28T02:15:14.545Z","0.12.95":"2022-06-28T02:56:04.824Z","0.12.95-alpha.1":"2022-07-08T07:28:08.213Z"},"homepage":"https://github.com/teambition/teambition-sdk#readme","keywords":["teambition","sdk","teambition-sdk"],"repository":{"type":"git","url":"git+ssh://git@github.com/teambition/teambition-sdk.git"},"author":{"name":"lynweklm@gmail.com"},"bugs":{"url":"https://github.com/teambition/teambition-sdk/issues"},"license":"MIT","readmeFilename":""}